Skip to content

When unit testing is not enough

June 19, 2008 by Przemysław Bielicki

I'd like to share my experiences about unit testing (using JUnit) Java servlets outside of the servlet container. Agile world tells us that we should automate as much tests as we can - it would be good if all aspects of the developed system are completely tested. We should test functional as well as non-functional requirements of our systems. But can all tests be automated? What is the REAL value of such tests? The reality brings us problems and pitfalls even experienced developers fall into. I will present such story regarding automated and manual testing of Java servlets.

The problem
Quite recently I had do develop some "proxy" servlets facilitating Ajax request from web browser to our middleware layer. We couldn't directly send Ajax requests because JavaScript security model doesn't allow to request data from other address than it was originally downloaded (similar restriction to Java Applet).

All right then, our servlets were not doing any amazing job (some input and output transformations were needed, however) but I made some bugs even having 100% test code coverage (used Cobertura 1.9).

What about automated tests?
Well some things can be automated, some not. Let's start with unit testing servlets. The simplest (containerless) solution to unit test servlets is to use EasyMock in order to provide mocks for HttpServletRequest, HttpServletResponse, etc. Yes, I know you can use Jakarta Cactus but I did it quicker using easy mock :)

OK - I unit tested my servlets and was very happy that I saw the green light. I started the sevlet container accessed the web page and it seemed to be working. Unfortunately I didn't see that the servlet set some instance variables after the first invocation and these variables couldn't be changed afterwards. The effect was disastrous - servlet was sending the same request all the times not taking into account passed parameters. We could have checked this problem by invoking my doXXX method multiple times with different parameters - we didn't.

Did we test our servlets manually?
Yes, non-automated tests were performed using JMeter. I used JMeter to check how our servlets behave under heavy load. The performance and load results were OK but I noticed in the logs many entries similar to this one:

Checkout date [2008-10-15] is earlier than or equals checkin date [2008-10-11]

Well the log message lies! And the implementation is well-coded (really). What's wrong?
This is how I discovered problem with SimpleDateFormat - not to mention the help from FindBugs that showed me big red light in the affected lines :)

What was wrong?

  1. I forgot that using instance variables is not thread-safe (there is only one servlet instance created by the container)
  2. I forgot that java.text.SimpleDateFormat has synchronization problems and cannot be used as a static class field
  3. I took UTF-8 for granted - unfortunately default encoding was set to the server's default one (this problem was not described above but it appeared during further manual UI testing)

Lesson learned
When you want to test your servlets:

  1. You should invoke all methods you test multiple times
  2. You should test your servlets using couple of simultaneous threads to see whether there is no shared data clash
  3. Be sure you set required content type and content encoding before you flush any response - DON'T take anything for granted
  4. You should use FindBugs to check any common Java problems (e.g. SimpleDateFormat) - either using Eclipse/NetBeans plugin or Maven report
  5. ALWAYS test your servlets under heavy load - what works for single user can stop working when many users try to use your application

Using load testing tools you can discover quite interesting and unexpected problems - without such test you cannot be sure your application will work under every circumstances.

After implementing all fixes our servlets seem to work very well even under heavy load. We don't have any thread-safety issues and our dates are parsed correctly ;)

Conclusion
To conclude shortly I will say that testing servlets is not easy. You can write unit test, "inject" mock request, response, etc. objects but you still will not be sure how your system behaves inside servlet container under heavy load (you should also try using Jakarta Cactus framework).
Agilists say that you should automate as much tests as you can. I generally agree with it but sometimes it makes more sense to perform some manual testing which simply works. I probably would not discover all the issues I revealed using only automated tests.

If you have other experiences with testing Java servlets, please share them here.

About the Author: Przemysław graduated from Gdańsk University of Technology in 2004 having specialized in Distributed Information Systems. He worked in Lufthansa Systems, Intel Corporation in the past where he developed complex IT solutions in many Java-related technologies. In professional life he is a real Java expert holding couple of Sun Java certificates (Programmer, Developer, Web Developer) and Certified Scrum Master, of course.

Przemysław is a regular contributor to AgileSoftwareDevelopment.com and the author of "From Java to Java EE" blog. He now works as a Software Craftsman in an international company that is the leading Global Distribution System (GDS) and the biggest processor of travel bookings in the world. Contact Przemysław

Comments

About SimpleDateFormat

June 19, 2008 by Riccardo (not verified), 1 year 2 weeks ago
Comment id: 1593

Nice you pointed to a very subtle issue with SimpleDateFormat :-)
It is strange how 99% of the people I worked with simply skipped the part in the docs where it explicitly says that instances for that class are not threadsafe (or they don't know what thread safety is about).
They usually implement it as a static field in some utility class without any kind of synchronization; when I stumple upon such terrible mistake I usually try to teach the writer about the fact that similar code WILL cause problems and you know what's the answer I get (always the same one!)? "we never had problems with that"!
next time I find myself in that situation I will try to link them this blog entry, hoping they believe at something that's wriitten.
Thanks

About SimpleDateFormat

June 19, 2008 by pbielicki, 1 year 2 weeks ago
Comment id: 1594

Like I wrote in my post there is a very simple and agile solution - use FindBugs - you will see this issue as an ERROR. It's enough for me :)

Findbugs and similar

June 19, 2008 by Riccardo (not verified), 1 year 2 weeks ago
Comment id: 1595

People I'm talking about almost don't know the existence of findbugs/pmd and such; simply they won't use them because "they give too many errors"!

Findbugs and similar

June 20, 2008 by pbielicki, 1 year 1 week ago
Comment id: 1596

OK - that's the real problem. But, if you use some continuous integration framework (Continuum, Bamboo, etc.) with Maven2 or even Ant script you could easily (at least using Maven2) add the plugin that will be automatically doing the check and sending emails in case of errors or even warnings (depending on the threshold you set)

But anyway - changing the way people think and work is the biggest problem and challenge...

There is a trick to use when introducing findbugs and similar

June 23, 2008 by Sergey Pashin (not verified), 1 year 1 week ago
Comment id: 1597

Exactly, that is the one of the most popular reasons. The trick is this: First just let the Continuous Integration system run findbugs, pmd an alike and show the team the trend of defects found by static analysis such as one provided by our Parabuild. Once the team got used to the fact that there is a system that automatically detects defects, you can begin looking at the most dangerous ones and fixing them, one by one. The trend would go down nicely. When all issues are fixed, it is now possible to ask the team members to run static analysis before checking in new changes and to turn on failing build when any of the issues pop up.

Sergey

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Allowed HTML tags: <a> <b> <i> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <img> <br> <blockquote>
  • Lines and paragraphs break automatically.
  • Web page addresses and e-mail addresses turn into links automatically.
  • You can enable syntax highlighting of source code with the following tags: <code>, <blockcode>. Beside the tag style "<foo>" it is also possible to use "[foo]".

More information about formatting options

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.

Best of AgileSoftwareDevelopment.com