Integration tests

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.

Tests separation

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

Let us write a simple integration test.

The integration test

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.

The integration test

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:

The integration test

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.

The integration test

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).

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.16.79.65