Does anyone have experience writing UnitTest
s for servlets? The problem we are running into is that setting up the environment to run a servlet is extremely complicated.
Course of the discussion has nothing to do with Servlet testing, but it is about web applications testing. IMO: 99% web applications do not need custom Servlets at all! MVC2 paradigm (look at Struts http://jakarta.apache.org/struts as an implementation) eliminates need for them and simplifies Java web development enormously (testing too). Good testing tools are HttpUnit and Cactus (http://jakarta.apache.org/cactus/)
I've done some, with an adapter I wrote that lets you create the request
object, hand it to the servlet, then interrogate the response object. It's
available at http://www.iac.net/~crawford/programming/testharness.zip
Actually, I have done some work adapting JavaUnit
to work with Servlets. I didn't take the approach you did though - I wrote a subclass of TestCase
that contains utility methods to invoke a servlet URL with a GET or POST request and pass HTTP parameters to the request. I then get back the result from running the servlet (the HTTP) and then parse it to determine if the test passed or failed.
This way you don't have to mess with setting up the servlet environment specially.
Kyle, can you post your JUnit extension mentioned above?
The problem with this approach, though, is the same one I encountered with
some of my first CGI scripts: failures that generate incorrect output are
easy to spot, but more serious errors are opaque. JUnit's nice exception
traces won't do you any good. -- GlennVanderburg
To test ActiveServerPages
I have ended pushing as much of the application out of the ASP and behind a facade. I can then UnitTest
the facade. We combine this with non-automated testing (people with a check list in front of a browser). -- FabianLeGayBrereton
I try to just have interface code (HTML) in the ASP. The ASP interacts with the model through the facade (a COM/MTS component). MartinFowler
discusses this in an article on ApplicationFacades
Apart from allowing the application to be more easily tested this also overcome problems with ASPs crappy exception handling and debugging.
An Excellent approach. I do this too with Servlets and JavaServerPages
. If you think of your Servlets and JSP's as being the "view" and "controller" layers in an MVC architecture, you should be able to test the "model" layer separately.
There are servlet frameworks that encourage this approach, too, such as webmacro and possibly enhydra (although I haven't really looked at the latter).
My favourite framework for this is freemarker. http://freemarker.sourceforge.net/
Our experience reinforces that of Kyle - the more you test in the model the better. We almost view our Servlet testing as being on par with functional tests in that we run them less often (only several times a day vs. hourly). The real tests are run at the unit level on model classes.
We used to do a lot of opening a socket to a servlet and comparing expected output with actual output - but we have backed of this a bit as its slow, very fragile to changes unless you repeat much of the code you were using to generate the output in the first place. We are starting to move more down the road of creating a result model - which we can query and verify in unit tests. You then test that each result piece can render itself out into html (probably by some painter object - but often the simplest thing is to start with toString to get it going).
Finally you can get a lot of mileage from stuffing a HashTable
into an Http
Request with known key,value pairs and testing that some Factory like object extracts the values and creates the objects you want (or stuffs them back into an existing object). This way you can test more without having real servlets and having to rely on post and get routines. This object can also do your validation and answer your error messages which your servlet can then send back. Using this approach means that your servlet starts looking skinnier and skinnier (unlike many of the articles you see in magazines) -- TimMackinnon
I too have been looking at ways of testing servlets and JSPs. My current approach is what has been suggested above - separate the model from the view (JSP) which allows you to write your UnitTest
code for the model.
However, I would still like to test the JSPs. My feeling is that there are several things that need to be tested which would be helped a great deal by ensuring that the documents generated from the JSP are well-formed XML. You can then use a parser to validate the document and find expected elements.
As a result of this I too am tinkering with extensions to JUnit which enable easy testing of JSP output.
Has anyone tried this approach ? Or am I barking mad? :-)
There seems to be a fair amount of interest in unit testing servlets, what do people feel are important features for unit testing servlets? Here are some of my ideas off the top of my head:
- XML Validation
- Finding HTML (DOM) elements and verifying that they contain expected attributes etc
- Finding strings
- Coping with authentication
- Handling cookies (i.e. the server will want to use them)
- Building HTTP POST and GET requests
- Verifying that response codes are as expected
There are loads more but what I'd like to know is what is important ?
Though perhaps not strictly a servlet test, a way of testing a system of servlets with bombardment of concurrent requests would be useful (so useful I'm sure it's been done before, but I can't remember seeing it anywhere).
I've implemented a rudimentary extension to JUnit 3.2, junit.servlet.TestRunner
so that you can have the request and response objects available in your TestCase
objects (for those objects that just have to have the complete context before you can test them). Right now it is written for SilverStream
, I'll be making a PlainJane?
Servlet version in the next few days. -- PeteMcBreen
Details are on EnhancingJunit
page, code is at http://www.mcbreen.ab.ca/pete/TestRunner.java
Yet another framework for testing servlets can be found at http://www.egroups.com/files/extremeprogramming/servlettesting.zip
. It provides dummy implementations for most classes in javax.servlet.http and extends them with setters and getters for testing.
I believe testing should also happen end-to-end. For our Web application framework we also created the necessary infrastructure to do performance and functional testing, where functional testing is embedded in our automated daily build and (unit) testing process. However, our stuff is C++ based and not Java.
I downloaded the TestRunner PeteMcBreen
posted and ran it. He did a great job. I needed to be able to access the Http
Request and the Http
Response, so I modified JavaUnit
to allow me to pass them to the TestCase
. I also pass the Print
Writer to TestCase
, that way I can output text to the browser instead of System.out.println. The problem I have is passing values through the request. I was trying to find a way to change the request. The only way I can get them there is from a page... However, JavaUnit
and running Tomcat in a debugger work very well. If anyone wants the changes to JavaUnit
, send me and e-mail. I did this once before for AtgDynamo
. I think JavaUnit
needs a mechanism to pass parameters to TestCase
2000 Presentation - Servlet Unit Testing: http://www.delphis.com/javacon2000/servlet.html
J2EEUnit has been renamed Cactus and absorbed into Apache's Jakarta project. It is now at http://jakarta.apache.org/cactus/
. Also interesting is the mockobjects project at http://www.mockobjects.com
, which provides mock versions of the HTTP servlet request, response, and session objects, as well as many others.
. -- GarethCronin