GDocx 3.0.0 released

GDocx, the fluent interface to the Docx4J library, version 3.0.0 has been released.

What’s new ?

GDocx now uses the latest (3.0.1) Docx4j version.

Other changes includes replacement of Fest Assert with the AssertJ library which is more flexible and powerful.

All files, including source and javadoc can be downloaded from the project home at the https://java.net/projects/gdocx

Advertisements

Tutorial: using Mockito

Mockito (http://code.google.com/p/mockito/) is a Java mocking library which is very useful in unit testing but also to simplify and enhance the integration tests.

There are different situations where Mockito can be used and each situation requires a different approach and different Mockito usage.

In this tutorial I will show how I implement unit tests for middle (service, business logic) layer classes.

In the examples below I will use the Spring Framework demo project named PetClinic and available at https://github.com/spring-projects/spring-petclinic but the article contents does not depend on any Spring features.

To use Mockito I added the following dependency to the project pom.xml :

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>1.9.5</version>
    <scope>test</scope>
</dependency>

We will also use AssertJ (link):

<dependency>
    <groupId>org.assertj</groupId>
    <artifactId>assertj-core</artifactId>
    <version>1.3.0</version>
    <scope>test</scope>
</dependency>

Inside the PetClinic demo there is the ClinicService which is a Springs Service bean. The interface is org.springframework.samples.petclinic.service.ClinicService while the implementing class is org.springframework.samples.petclinic.service.ClinicServiceImpl.

The ClinicService has several dependencies to the application lower level, the DAO / Repository level:

private PetRepository petRepository;
private VetRepository vetRepository;
private OwnerRepository ownerRepository;
private VisitRepository visitRepository;

The ClinicService is tested by AbstractClinicServiceTests and its 3 different implementations (using 3 different DB access Spring solutions: direct JDBC, JPA and Spring Data).

Actually these tests are integration tests because the class under test (ClinicService) is using, during the test, its real dependencies (the repositories) and so it is not isolated.

By the way, PetClinic demo does not use the standard naming convention for the tests (at least for maven projects) which is the following:

  • *Test.java or Test*.java for unit tests (Surefire plugin)
  • *IT.java or IT*.java for integration tests (FailSafe plugin)

In PetClinic, all tests (unit and integration) are named *Tests.java (“Tests” instead of “Test”) so Surefire plugin has been customized as following:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.13</version>
    <configuration>
        <includes>
            <strong><include>**/*Tests.java</include></strong>
        </includes>
    </configuration>
</plugin>

In this tutorial, I will follow their convention even if it is not what I usually do in my projects.

Let’s unit test ClinicService with the help of jUnit and Mockito.

First step is to create the test class and instantiate the ClinicService implementation class:

public class ClinicServiceImplTests {
    private ClinicServiceImpl sut;
}

A couple of comments:

  • I use the implementing class and not the interface. Using the implementing class, let us access to the class protected methods (if any), not accessible using the interface.
  • The instance name of the class to be tested is usually sut (which stays for “system under test”) to help myself and other test code readers to easily identify the class we are testing. Cut (for “class under test”) is also used (by others) but I prefer sut because it is more generic.

We need now to instantiate the ClinicServiceImpl and, to avoid dependencies among tests, I use the jUnit before method

@Before
public void setUp() throws Exception {
    sut = new ClinicServiceImpl(petRepository, vetRepository,
        ownerRepository, visitRepository);
}

ClinicServiceImpl costructor requires the 4 repositories: we will create mocked versions of the real ones (to break the dependency between ClinicServiceImpl and the repositories).

To create the mocks:

@Mock private OwnerRepository ownerRepository;
@Mock private PetRepository petRepository;
@Mock private VetRepository vetRepository;
@Mock private VisitRepository visitRepository;

@Mock is a Mockito annotation which need a jUnit TestRunner to be activated. We should add @RunWith(MockitoJUnitRunner.class) as class annotation.

After all these changes we have

@RunWith(MockitoJUnitRunner.class)
public class ClinicServiceImplTests {
    private ClinicServiceImpl sut;
    @Mock private OwnerRepository ownerRepository;
    @Mock private PetRepository petRepository;
    @Mock private VetRepository vetRepository;
    @Mock private VisitRepository visitRepository;

    @Before
    public void setUp() throws Exception {
        sut = new ClinicServiceImpl(petRepository, vetRepository,
            ownerRepository, visitRepository);
    }
}

One important comment to do is that we are NOT using any Spring features (like @Autowire or @ContextConfiguration) in the test. We do not depend on Spring and we will also enjoy a faster test execution because Spring framework will not be loaded.

Spring allows us to use setter to inject repositories as alternative to constructor injection used in the demo. For example we could have in the implementation class something like the following:

private OwnerRepository ownerRepository;
.... other fields
@Autowired
public void setOwnerRepository(OwnerRepository pOwnerRepository) {
    this.ownerRepository = pOwnerRepository;
}
..... other setters

In this case, in the test setup method we will have:

sut = new ClinicaServiceImpl();
sut.setOwnerRepository(ownerRepository);
.....other calls to sut setters

We are ready now to test ClinicServiceImpl (our sut) behaviour.

Let’s start with a ClinicServiceImpl method which is a good (even if very simple) example of a method which receives data from one of its dependencies (ownerRepository in this case).

Method (from ClinicServiceImpl) is

public Owner findOwnerById(int id) throws DataAccessException {
    return ownerRepository.findById(id);
}

Following my TDD habits, the test is:

/**
* Pet owner can be found using its ID
*/
@Test
public void findPetOwnerById() {
    // given
    final int id = 123;
    Mockito.doReturn(createOwner()).when(ownerRepository).findById(id);
    // when
    final Owner res = sut.findOwnerById(id);
    // then
    assertThat(res).isNotNull();
}
private static Owner createOwner() {
    return new Owner();
}

Comments:

  • the method comment helps to clarify the purpose of the test which should be also reported in the method name. Thankfully, there is no more need to use old jUnit 3 “test***” naming convention.
  • the test method body is divided in three sections:
    • given: all data (test fixture) preparation
    • when : method to be checked invocation
    • then : checks and assertions
  • createOwner() is a support private method to create a very basic Owner.
  • in the when section I usually name the result of the method (if not void) as “res” (result). Again this is to make test code clearer.
  • in the then section I usually uses AssertJ fluent assertion library. See here for more details about AssertJ library. We will see later how Assertj let us to be more efficient in our verification step.
  • findOwnerById() does not change the Owner instance returned by ownerRepository so there is no meaning to check Owner fields value. In other cases, I use more detailed assertions (like assertThat(res.getId()).isEqualTo(123)) than the isNotNull().

The key element is here is the line:

Mockito.doReturn(createOwner()).when(ownerRepository).findById(id);

which says:

dear Mockito, during the test execution, when someone (the findOwnerById method in our case) will invoke the ownerRepository.findById() method with int 123 as argument, please return the Owner instance created by createOwner()

Without this line, ownerRepository.findById() will return null. This is the standard behavior for Mockito.

Specifying the int value (123) will let us to filter ownerRepository.findById() invocations:

  • ownerRepository.findById(123) with return a not null Owner
  • ownerRepository.findById(44) will return a null

If we cannot be so accurate about the argument (for example, when method argument is calculated by the method under test), we can use

Mockito.doReturn(createOwner()).when(ownerRepository).findById(Mockito.anyInt());

to say Mockito to return a not null Owner regardless the findById parameter value.

Let’s now test another method from ClinicServiceImpl which send data to a dependency:

public void savePet(Pet pet) throws DataAccessException {
    petRepository.save(pet);
}

The test is :

@Test
public void savePet() {
    // given
    final Pet pet = createPet();
    // when
    sut.savePet(pet);
    // then
    Mockito.verify(petRepository, Mockito.times(1)).save(pet);
}
private static Pet createPet() {
    Pet pet = new Pet();
    pet.setName("My little Pet");
    return pet;
}

The structure is the same but here we use Mockito for a different purpose: to check if a method is invoked or not and how many times.

The line

Mockito.verify(petRepository, Mockito.times(1)).save(pet);

says:

Dear Mockito, please check during the test execution, that petRepository.save() will be invoked one time (no zero, no more than one) and with the argument pet (as it is created by the createPet() support method).

If the method petRepository.save() is not invoked or invoked more than one times or invoked with a different pet, verify will rise a test failure exception.

Comment: Mockito.times(1) is the default so we can write the same line as

Mockito.verify(petRepository).save(pet);

Do not be confused by the fact that Mockito.verify is specified in the then section, after the petRepository.save() invocation (in the when section). Mockito always collect all methods invocation data. The verify istruction just compare what happened with what we expect.

Now we can move to a more complicated example but the ClinicService is too simply. Let me add to it the following method:

@Override
@Transactional
public void adoptAPet(Owner owner, Pet pet) {
    if (pet != null) {
        owner.addPet(pet);
        ownerRepository.save(owner);
    }
}

The method let an owner to adopt a pet.

Its test can be:

/**
* Pet adoption with a real pet
*/
@Test
public void petAdoptionWithRealPet() {
    // given
    final Owner owner = createOwner();
    final Pet pet = createPet();
    final ArgumentCaptor<Owner> ownerCaptor = ArgumentCaptor.forClass(Owner.class);
    // when
    sut.adoptAPet(owner, pet);
    // then
    Mockito.verify(ownerRepository).save(ownerCaptor.capture());
    assertThat(ownerCaptor.getValue().getPets()).hasSize(1).contains(pet);
}

We want now to find which is the argument of the ownerRepository.save() invocation inside the adoptAPet() body. In other words we want to intercept the call to ownerRepository.save() and get the value of its argument.

This is a three steps approach.

First step is to prepare a dedicated parameters captor (something that will capture the method argument) with:

ArgumentCaptor<Owner> ownerCaptor = ArgumentCaptor.forClass(Owner.class);

where Owner is the ownerRepository.save() argument type.

Second step is to ask verify to save the parameter value in our captor with the following line:

Mockito.verify(ownerRepository).save(ownerCaptor.capture());

Verify will not only check if the ownerRepository.save() is invoked only once but also it will save its argument value (with the captor capture() method).

Final step is to get the captured argument value using the ownerCaptor.getValue() method (which in our case returns the Owner instance used to invoke ownerRepository.save()) and to assert its contents.

In the test I used AssertJ power to check if owner.getPets() collection has size 1 and contains the same pet I passed to the adoptAPet() (when section):

assertThat(ownerCaptor.getValue().getPets()).hasSize(1).contains(pet);

The ArgumentCapture is a very powerful tool which let us to get internal data if used as method argument to mocked dependencies.

The adoptAPet() method handles the null case for the pet parameter so let’s test this behavior:

/**
* Pet adoption do nothing if pet is null
*/
@Test
public void petAdoptionWithNullPet() {
    // given
    final Pet pet = null;
    final Owner owner = createOwner();
    // when
    sut.adoptAPet(owner, pet);
    // then
    //Mockito.verify(ownerRepository, Mockito.never()).save(Mockito.any(Owner.class));
    // or
    Mockito.verifyZeroInteractions(ownerRepository);
}

Here we want to be sure that ownerRepository.save() is not invoked when the pet parameter is null.

Two different solutions are possible: we can verify that the ownerRepository has not been used (which means none of its method has been used) with the following:

Mockito.verifyZeroInteractions(ownerRepository);

or verify that the ownerRepository.save() is never invoked with the following:

Mockito.verify(ownerRepository, Mockito.never()).save(Mockito.any(Owner.class));

leaving the possibility that other ownerRepository methods can be invoked. In this case, I can use Mockito.any(Owner.class) as save() parameter because here the save() argument value is not important.

This tutorial has shown different ways to use Mockito (and AssertJ) to create a unit test for a middle layer class. The ClinicServiceImpl class was intrinsically testable and we could easily break its dependencies without code refactoring.

This is not always the case. In future articles I will show how I handle difficult to test classes and also how Mockito can help in integration tests.

Final comment is how I have used Mockito in the above examples: I did not use static imports to help you to identify Mockito instructions but please be aware that all instructions can be shortened. For example

Mockito.verify(ownerRepository, Mockito.never()).save(Mockito.any(Owner.class));

becomes

verify(ownerRepository, never()).save(any(Owner.class));

with the proper static imports. Ask your preferred IDE to help you.

All files I have modified/added to the PetClinic application can be found here.