1

The current approach is creating HTML in a ServletTest, run the test, change the Servlet until the test turns into green. However, it feels like that this approach to TDD in Servlets is devious and more time-consuming than TDD ordinary Java classes as HTML created in the ServletTest is copied to the Servlet for the most part and subsequently changed regarding the format (e.g. removing backslashes) instead of testing the output in a Test for ordinary Java Classes and writing most of the code in the main.

ServletTest:

HttpServletRequest mockedHttpServletRequest = mock(HttpServletRequest.class);
HttpServletResponse mockedHttpServletResponse = mock(HttpServletResponse.class);
HttpSession mockedHttpSession = mock(HttpSession.class);

StringWriter stringWriter = new StringWriter();
PrintWriter printWriter = new PrintWriter(stringWriter);

private final String doGetHtmlStringPartOne = "<html><body><table>"
        + "<tr><td><h1>";
private final String doGetHtmlStringPartTwo = "<\\/h1><\\/td>"
        + "<form method=\"post\">"
        + "<input type=\"hidden\" name=\"randomDigitRange\" value=\"1\" \\/>"
        + "<input type=\"hidden\" name=\"randomMathematicalOperator\""
        + " value=\"1\" \\/><input type=\"hidden\" name=\"fractionBoolean\""
        + " value=\"";

private final String doGetHtmlStringPartThree = "<td><input type=\"radio\" name=\"userInput\" value=\"(\\d)+.(\\d)+\">(\\d)+(\\s\\/\\s(\\d)+)?<\\/td>";

private final String doGetHtmlStringPartFour = "<\\/tr><tr><td>"
        + "<input type=\"submit\" value=\"Submit\" "
        + "onclick='this.form.action=\"ToBeDefinedServlet\";' \\/>"
        + "<\\/td><\\/tr><\\/table><\\/form><\\/body><\\/html>"
        + "<form action=\"\\/tobedefinedservlet\">"
        + "<input type=\"submit\" value=\"Home\"><\\/form>";

@Test
public void testBooleanFractionTrue() throws IOException, ServletException {
    mockDoGet();
    assertTrue(stringWriter.getBuffer().toString().trim().matches(expectedDoGetHtmlString("1 \\/ 1 \\+ 1 \\/ 1", true)));
}

public String expectedDoGetHtmlString(String assignment,
        Boolean fractionBoolean) {
    return doGetHtmlStringPartOne + assignment + doGetHtmlStringPartTwo
            + "" + fractionBoolean + "" + "\" \\/>" + "\\n"
            + doGetHtmlStringPartThree + "\\n" + doGetHtmlStringPartFour;
}

public void mockDoGet() throws IOException, ServletException {
    when(mockedHttpServletRequest.getSession()).thenReturn(
            mockedHttpSession);
    when(mockedHttpServletResponse.getWriter()).thenReturn(printWriter);
    when(mockedHttpServletRequest.getParameter("fractionBoolean"))
            .thenReturn("true");
    when(mockedHttpServletRequest.getParameter("randomDigitRange"))
            .thenReturn("1");
    when(
            mockedHttpServletRequest
                    .getParameter("randomMathematicalOperator"))
            .thenReturn("1");
    when(mockedHttpServletRequest.getSession()).thenReturn(
            mockedHttpSession);
    new ToBeDefinedServlet().doGet(mockedHttpServletRequest,
            mockedHttpServletResponse);
}

Servlet:

protected void doGet(HttpServletRequest request,
        HttpServletResponse response) throws ServletException, IOException {
    calculation.setFractionBoolean(Boolean.parseBoolean(request
            .getParameter("fractionBoolean")));
    calculation.setAssignment(Double.parseDouble(request
            .getParameter("randomDigitRange")), Double.parseDouble(request
            .getParameter("randomMathematicalOperator")));
    PrintWriter out = response.getWriter();

    out.println("<html><body><table>"
            + "<tr><td><h1>"
            + calculation.getAssignment()
            + "</h1></td>"
            + "<form method=\"post\">"
            + "<input type=\"hidden\" name=\"randomDigitRange\" value=\""
            + request.getParameter("randomDigitRange")
            + "\" />"
            + "<input type=\"hidden\" name=\"randomMathematicalOperator\" value=\""
            + request.getParameter("randomMathematicalOperator") + "\" />"
            + "<input type=\"hidden\" name=\"fractionBoolean\" value=\""
            + request.getParameter("fractionBoolean") + "\" />");

    for (double possibleAnswer : calculation.getPossibleAnswersArray()) {
        String possibleAnswerFormat = Boolean.parseBoolean(request
                .getParameter("fractionBoolean")) == true ? ""
                + new Fraction(possibleAnswer) + "" : "" + possibleAnswer
                + "";

        out.println("<td><input type=\"radio\" name=\"userInput\" value=\""
                + possibleAnswer + "\">" + possibleAnswerFormat + "</td>");
    }

    out.println("</tr>"
            + "<tr><td><input type=\"submit\" value=\"Submit\" "
            + "onclick='this.form.action=\"ToBeDefinedServlet\";' /></td>"
            + "</tr></table></form></body></html>"
            + "<form action=\"/tobedefinedservlet\"><input type=\"submit\" value=\"Home\"></form>");
}
030
  • 10,842
  • 12
  • 78
  • 123
  • 5
    I think the main problem is that you are building your html page this way to begin with. Why aren't you using JSF or some similar technique instead? – Keppil Jun 28 '14 at 11:48
  • 1
    This is an _integration test_. You are simulating the browser. Your HTML should be generated in a **template** using some **templating engine**. This engine takes **data** as input. You should be testing the methods that generate that **data** not the HTML. – Boris the Spider Jun 28 '14 at 11:51
  • @Keppil I am following [these steps](http://docs.oracle.com/javaee/6/tutorial/doc/gjaam.html) to implement JSF. However, `The import javax.faces cannot be resolved`. I am using jdk8 and trying to solve this issue, because the JSF answers the question. Thank you for the advice. – 030 Jun 28 '14 at 15:13
  • JSF is not a part of Java SE. Of course you get a compilation error. – Marko Topolnik Jun 28 '14 at 19:41
  • It works after importing the correct library – 030 Jun 28 '14 at 19:42
  • @Keppil Perhaps you could post the comment as an answer, as it answers the question. – 030 Jul 10 '14 at 16:21
  • @utrecht: Answer posted. See if you have any more comments, or if I have left anything out. – Keppil Jul 10 '14 at 16:29

1 Answers1

1

I think the main problem here is that you are building your html page by manually putting the html elements together from various strings. As you have experienced, this leads to code that is hard to test and maintain.

Try using JSF or some simliar technique instead. This will enable you to focus only on the functionality on the Java side, which is much easier to test.

Keppil
  • 45,603
  • 8
  • 97
  • 119