There is no doubt that any piece of software should have automated tests. Tests assure us that by adding a new functionality, we are not breaking anything that has been already done. Tests document the software. Tests decrease the amount of manual debugging. After reading a number of articles and books about automated tests, you can actually believe that automated tests are the panacea for all the evil in the software development world. And Java backend microservice application is no different.

Unfortunately, there is no magic in tests. Tests need to be well written to provide any value. Moreover, a misunderstood idea of automated tests can be even worse than having no tests at all, as they will trick you with false feedback.

How to prepare a proper suite of tests for a simple Java microservice?

First of all, we need to make sure that modules composing our application work well. Constraints, validation, specific business rules applied to your value objects are to be checked by unit tests. Also, all kinds of serializing, deserializing, marshaling, equals and hashcode contracts need to be tested.

Always use proper tools!

One of the most useful ones is EqualsVerifier. No matter how big the DTO class is, the hashcode and equal contract test are reduced to a couple of lines:

The other tip is to use “ObjectMothers”. They are factory classes which provide you with instances of objects you use in your tests. The idea behind them is to reduce code duplication (imagine you had to add a new field to MyClass and update all the tests!) and enhance tests readability by providing descriptive factory method names. (more about: martinfowler.com/bliki/ObjectMother.html)

Also you might like to check out AssertJ: joel-costigliola.github.io/assertj/ AssertJ eases writing and reading assertions. Your validation test can be as descriptive as:

Keep in mind that tools are not everything

Remember to check more than a happy path.
Take a look at this little method and pretend that getting those distinct numbers takes a lot of complicated code.

Can you think of test scenarios?
You should check:

  • some duplicates like 1,1,2,4,4,10
  • non duplicated 1,2,3
  • empty array
  • and of course: null

Be sure to use your IDE code coverage plugin to make sure that you did not omit anything!

Having separated modules covered by unit tests, it’s time to move towards integration testing. Those are very convenient because they actually describe what the system does. Moreover, short tests with descriptive names are a valuable source of knowledge for a developer who has just joined the project. If the code has all the details, integration tests can be treated as bullet points, giving a brief description of what the code should do.

However, for the best effect, some preparation must be made: we need to hide all the plumbing to preserve clarity. In Neoteric, we provide a base class with protected instances of everything needed, the basic idea looks similar to:

All we need to add are some utility methods and classes to map responses, generate test objects, and we are good to go!

We will cover this by an example. We want to check if our application will serve a JSON with a customer from customers’ collection when an HTTP GET request is invoked on “/api/customers/{id}” path. The basic tool is Jayways REST assured (you definitely need to take a look at github.com/jayway/rest-assured )

Let’s take a quick look:

That’s it! You’ve just made sure that data from the database successfully passed all the tiers of your application, from byte representation in DB to a JSON ready for consumption by a client.

Remember that the happy path is deceitful. To make sure that your endpoint works properly, you need to check how it behaves when a malformed or non-existing customer ID is requested, what happens when a user is not authorized to such request and other examples specific to your application.

Remember also that Robert Martin wants you to keep your tests as clean as production code – tests are first-class citizens of your application!

Read also: Make programming easier! Introducing Lombok to your Java code