Test code readability improved: JUnit with Mockito and FEST Fluent Assertions
To improve the readability of my unit tests I use assertThat with Hamcrest matchers. This is a good way to improve readability of your test code, especially when I statically import members of like org.junit.Assert.assertThat and org.hamcrest.Matchers. But when I add Mockito matchers on top of it, I experienced the problem of static import conflicts that ended up with "not nice" code (according to my definition).
Let's look at the (hypothetical) example:
Then, some time ago, someone mentioned on Twitter that I should try FEST Fluent Assertions. So I gave it a try and I ended up with the below:
import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import static org.junit.Assert.assertThat; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.class) public class UserServiceTest { @InjectMocks private UserService userService = new UserService(); @Mock private UserRepository userRepositoryMock; @Test public void returnsUserDetailsFoundInRepository() { // arrange User demoUser = new User("user", "demo", "ROLE_USER"); when(userRepositoryMock.findByUsername("user")).thenReturn(demoUser); // act User userDetails = userService.loadUserByUsername("user"); // assert assertThat(userDetails.getUsername(), org.hamcrest.Matchers.startsWith("user")); verify(userRepositoryMock).findByUsername(org.mockito.Matchers.startsWith("user")); } }In the assert section I must choose to statically import either org.hamcrest.Matchers.startsWith or org.mockito.Matchers.startsWith. And I don't really like it.
Then, some time ago, someone mentioned on Twitter that I should try FEST Fluent Assertions. So I gave it a try and I ended up with the below:
import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import static org.fest.assertions.Assertions.assertThat; import static org.mockito.Matchers.startsWith; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.class) public class UserServiceTest { @InjectMocks private UserService userService = new UserService(); @Mock private UserRepository userRepositoryMock; @Test public void returnsUserDetailsFoundInRepository() { // arrange User demoUser = new User("user", "demo", "ROLE_USER"); when(userRepositoryMock.findByUsername("user")).thenReturn(demoUser); // act User userDetails = userService.loadUserByUsername("user"); // assert assertThat(userDetails.getUsername()).startsWith("user"); verify(userRepositoryMock).findByUsername(startsWith("user")); } }The changes are:
-
import static org.fest.assertions.Assertions.assertThat instead of import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.startsWith;
@Test public void returnsMostActiveUsers() { ListTo have all libraries available with Maven the following dependencies should be used:users = userService.getMostActiveUsers(); assertThat(users) .hasSize(3) .containsOnly(userWith10Activities, userWith5Activities); }
<!-- Test --> <dependency> <groupId>junit</groupId> <artifactId>junit-dep</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <version>1.9.5</version> <scope>test</scope> </dependency> <dependency> <groupId>org.easytesting</groupId> <artifactId>fest-assert</artifactId> <version>1.4</version> <scope>test</scope> </dependency> <dependency> <groupId>org.hamcrest</groupId> <artifactId>hamcrest-core</artifactId> <version>1.3</version> <scope>test</scope> </dependency> <dependency> <groupId>org.hamcrest</groupId> <artifactId>hamcrest-library</artifactId> <version>1.3</version> <scope>test</scope> </dependency> <dependency> <groupId>org.objenesis</groupId> <artifactId>objenesis</artifactId> <version>1.3</version> </dependency>All of the above you can find on Github: Unit Testing Demo and in Spring MVC Quickstart Archetype.