We did a lot of unit tests. We relied a lot on trust. Unit after unit was specified and implemented. While working on specifications, we isolated everything but the units we were working on, and verified that one invoked the other correctly. However, the time has come to validate that all those units are truly able to communicate with MongoDB. We might have made a mistake or, more importantly, we might not have MongoDB up and running. It would be a disaster to discover that, for example, we deployed our application, but forgot to bring up the DB, or that the configuration (IP, port, and so on) is not set correctly.
The integration tests' objective is to validate, as you might have guessed, the integration of separate components, applications, systems, and so on. If you remember the testing pyramid, it states that unit tests are the easiest to write and fastest to run, so we should keep other types of tests limited to things that UTs did not cover.
We should isolate our integration tests in a way that they can be run occasionally (before we push our code to repository, or as a part of our Continuous Integration process) and keep unit test as a continuous feedback loop.
If we follow some kind of convention, it is fairly easy to separate tests in Gradle. We can have our tests in different directories and distinct packages or, for example, with different file suffixes. In this case, we choose the later. All our specification classes are named with the Spec
suffix (that is, TicTacToeSpec
). We can make a rule that all integration tests have the Integ
suffix.
With that in mind, let us modify our build.gradle
file.
First, we'll tell Gradle that only classes ending with Spec
should be used by the test
task:
test { include '**/*Spec.class' }
Next, we can create a new task testInteg
:
task testInteg(type: Test) { include '**/*Integ.class' }
With those two additions to the build.gradle
, we continue having the test tasks that we used heavily throughout the book; however, this time, limited only to specifications (unit tests). In addition, all integration tests can be run by clicking the testInteg
task from the Gradle projects IDEA window or running the following command from command prompt:
gradle testInteg
We'll create a TicTacToeInteg
class inside the com.packtpublishing.tddjava.ch03tictactoe
package in the src/test/java
directory. Since we know that Jongo throws an exception if it cannot connect to the database, a test class can be as simple as the following:
import org.junit.Test; import java.net.UnknownHostException; import static org.junit.Assert.*; public class TicTacToeInteg { @Test public void givenMongoDbIsRunningWhenPlayThenNoException() throws UnknownHostException { TicTacToe ticTacToe = new TicTacToe(); assertEquals(TicTacToe.NO_WINNER, ticTacToe.play(1, 1)); } }
The invocation of assertEquals
is just as a precaution. The real objective of this test is to make sure that no Exception
is thrown. Since we did not start MongoDB (unless you are very proactive and did it yourself, in which case you should stop it), test
should fail.
Now that we know that the integration test works, or in other words, that it indeed fails when MongoDB is not up and running, let us try it again with the DB started. To bring up MongoDB, we'll use Vagrant to create a virtual machine with Ubuntu OS. MongoDB will be run as a docker.
Make sure that the 04-integration
branch is checked out:
From the command prompt, run the following command:
$ vagrant up
Be patient until VM is up and running (it might take a while when executed for the first time, especially on a slower bandwidth). Once finished, rerun integration tests.
It worked, and now we're confident that we are indeed integrated with MongoDB.
This was a very simplistic integration test, and in the real world, we would do a bit more than this single test. We could, for example, query the DB and confirm that data was stored correctly. However, the purpose of this chapter was to learn both how to mock and that we should not depend only on unit tests. The next chapter will explore integration and functional tests in more depth.
The source code can be found in the 04-integration
branch of the tdd-java-ch06-tic-tac-toe-mongo
Git repository (https://bitbucket.org/vfarcic/tdd-java-ch06-tic-tac-toe-mongo/branch/04-integration).
3.16.79.65