I am a strong advocate of Test Driven Development. I strongly believe that, in order to deliver good software quality at sustainable speeds, you must have good tests.
Writing meaningful tests for a Java-EE application traditionally has been a rather cumbersome task. While mocking Frameworks like Mockito make it rather easy to test your classes in isolation, this kind of test usually has only limited value: while ensuring that the class in question does what it’s supposed to do, that alone does not guarantee you any desired system behavior exhibited by your application.
Use-case testing in Java-EE
In order to automatically test meaningful behavior your stakeholders are interested in, you usually have to consider a whole business use-case. In an application that usually means testing a number of classes working together, preferably in conjunction with some in-memory SQL database like H2. Other systems your application has to communicate with in order to fulfill the use-case usually have to be replaced with mocks to make your tests deterministic and repeatable.
At production runtime, dependency injection and resource resolution are performed by your application container (e.g. Wildfly or Glassfish).
At test runtime, this task has to be performed and integrated with alternative strategies like using an in-memory database and mocking some external systems. This is usually accomplished in one of two ways: using an actual heavyweight application container to run your tests in, or somehow providing a lightweight environment that is just enough to run your tests in.
The heavyweight option is well established and implemented by the Arquillian testing platform. The lightweight option on the other hand has been tackled by a small number of test runtimes like CDI-Unit, needle4j or BeanTest, none of which provides the feature set required for testing complex Java-EE applications. So after a really quick look at Arquillian in order to understand why heavyweight is not always your best option, we take a look at the new kid on the block for lightweight functional Java-EE testing: TestEE.fi (as in “testify”).
Heavyweight: Arquillian
Arquillian provides an environment suitable for running your tests by “simply” firing up the application server of your choice. It then packages your JUnit test cases into an enterprise application, deploys it to the application container and runs your tests there. This way it can rather effectively tell you if your application will run in its designated natural habitat in an automated and repeatable fashion. It however also comes with some relevant drawbacks:
- Arquillian does not address the issue of mocking away the systems surrounding your application at runtime. Mocking and stubbing classes or services in Arquillian tests seems to be cumbersome at best.
- Arquillian does not address database initialization (you’ll want some schema in that in-memory database of yours) and test data setup – so you’ll most likely end up writing something similar to what many others have done before to setup your database for testing.
- Having ever started an application server you know: this isn’t exactly the instantly-available kind of software. Starting up a Java-EE server and deploying an application (e.g. your JUnit tests) can easily take a minute or even more depending on your application’s configuration. Doing this on a per-Junit-test-class basis is something you’d probably rather avoid.
The startup time penalty hits a test-driven developer where it really hurts: the feedback-cycle-time. If it takes up to a minute or two to get feedback from even your fastest running tests, you end up running them way fewer times than you should. I’ve seen (and been part of) entire teams abandoning Arquillian for this very reason alone.
Lightweight: TestEE.fi
TestEE.fi aims to address these issues by taking an entirely different approach. While some (mostly non-functional) aspects of your application can often only really be ensured by running tests in an actual application container using a heavyweight framework like Arquillian, much (if not most) of your application’s business code requires only a tiny fraction of the services offered by a fully blown Java-EE compliant server.
TestEE.fi is a lightweight functional testing framework for Java-EE applications. By conveniently integrating a fully blown CDI implentation (TestEE.fi internally uses Weld, the CDI reference implementation) with much loved mocking frameworks like Mockito and EasyMock and proven database setup tools like Flyway and Liquibase it offers a natural way to write tests for your Java-EE application the same way you write your unit tests. And by integrating with test-runtimes like JUnit 4 & 5 or Cucumber JVM it allows you to run your tests directly from your preferred IDE and build tool – at speeds very close to unit-level testing.
Getting started
Getting started with TestEE.fi is really easy. First you need to add TestEE.fi to your project’s dependencies. In Maven this looks like the following snippet:
If you’re using Gradle, the snippet would look like this:
All you need to do now is to annotate your JUnit 4 test case like this:
When you run your new test class now, TestEE.fi handles dependency injection and mocking. For a number of example projects of various complexity go and check out the TestEE.fi examples repository – the “mocking” example project served as template for the sample code in this post.
Conclusion
This wraps up our first contact with TestEE.fi and leaves you with everything you need to get started with writing lightweight functional test cases for your Java-EE application.
If you want to know more about advanced testing with TestEE.fi, be sure to check out the other posts of this series to get you up to speed quickly:
- Part 2: Mocking with Mockito and EasyMock
- Part 3: JDBC and JPA
- Part 4: Cucumber JVM
- Part 5: JAX-RS and REST resources
- Part 6: JUnit 5
- Part 7: Static resources and Selenium (coming soon)
- Part 8: JMS and MDBs (coming soon)
Nice presentation!
Thank you for your feedback 🙂 The next installment with details on mocking with Mockito and EasyMock is already in the making and will be up soon!