I’m a big fan of testing code, so it seems appropriate to cover the basics of testing Spring web apps end to end. Although I’ll try to keep it on the basic side it is a huge topic and will be broken out into a series to give enough focus on distinct areas:
- Integration Testing Spring JPA (xml & java config)
- Unit test with Mockito
- Controller Unit Testing with Spring-mvc-test
- Controller Integration Testing with Spring-mvc-test
- Automated Browser Tests using Geb
- Code Coverage
- Load test with jMeter
- Reporting with Sonar
Integration Testing Spring JPA
Integration testing at the data layer is first. I chose to start with this for two reasons:
First is for those that love test driven development (TDD). When starting a project I suggest starting with the domain objects and build a solid object model for the app. Since most models are just getters/setters there is not much to test out of the gate. So the next logical step is to test how the models interact with the database and each other. It will save a lot of time to analyze the base queries and relationship mappings before getting to far along.
The second is for those who already have an app without tests or save tests for “hardening sprints” as the last step. Once you solve the Spring context for testing then the rest gets easier. Plus if you run out of time at least the tests will catch domain changes not rolled out to the database.
Unit test with Mockito
The next topic is unit testing. This part is critical if you care at all about testing code in isolation. Although integration testing can save time and make for some quick code coverage wins, unit tests isolate and can clearly tell you if your business logic works as expected. This is the testing that exercises logic branches, exceptions and things that can’t be replicated from the browser or integration test (like connection errors, bad data…)
Spring MVC Controller unit testing
After all the services, DAO’s and support classes are tested then it’s time for the controller. Generally this is hard to test and most developers (based on observation) would rather just test it via Selenium or worse, by hand. That can work but it makes testing logic branches difficult and not to mention it’s time consuming. Plus no active developer would be willing to wait for browsers tests to run before checking in code. Luckily the Spring mvc test project can do full controller testing via unit tests, it was such a success that is is now in Spring MVC core as of version 3.2.
Spring MVC Controller integration testing
Another look at the Spring MVC Test project (now part of Spring Test) and how to use it for full integration testing. We’ll load a WebApplicationContext with the application beans and let the MockMvc translate the request mappings.
Automated browser testing using Geb
Now comes the browsers testing, and I’m not going to use the same old selenium. Instead we’ll look at the Groovy alternative with Geb. Geb is built on top of Selenium drivers and brings the tests into a very readable format (DSL). Depending on your QA resource they might just write the tests for you. Geb can work with JUnit or Spock (I’ll use Spock for this example), it can be in the main project or if there are a ton of tests then it can stand alone test project. Get ready to love page models and jQuery like selector syntax!
Then my favorite… CODE COVERAGE!!! This also includes other static and active tools like PMD, findbugs and checkstyle. It’s the closest thing to a grade for your code. I think coverage has been abused at some organizations, the idea of 100% or else… is crap. Anyone can write a passing test and get code to execute. The whole point of the previous topics is to get meaningful tests, ones that run the code, test the logic and test the assumptions. Good tests give courage to refactor, find dead code, identify bad design and help protect against cowboy coders. From this mindset, code coverage becomes a power tool to highlight areas that may be light, at risk or even over executed (yes that happens, don’t write 10 tests when one covers it). If it’s all done right then the boss will love the pretty reports and the fact your code works.
Load test with jMeter
Now it’s time to hammer the app. You wrote it, it’s tested and you think it’s awesome. But does it work for more than one user? I like to use jMeter but there are plenty of load testers out there. In this example we’ll cover the basics of creating a test and getting results.
Reporting with Sonar
At this point you have a plethora of reports sitting in various folders. Some build servers will aggregate them for you or Sonar can come to the rescue. If you want team buy-in then running these tests must be automatic, fast and meaningful when they fail. There must be instant feedback and viewable in a single location. Colors, trends and graphs also don’t hurt.