JUnit 5 and Mokito
1. Mokito
Mockito empowers developers to create test doubles -- proxy objects that simulate real components -- enabling robust automated unit testing. This makes it an essential tool for test-driven development and a valuable ally in behaviour-driven development.
By isolating a single class for testing, Mockito allows developers to focus precisely on the behavior of that class, while interactions with other classes can be safely represented by lightweight mock objects, without requiring the full system to be operational. This leads to faster, more reliable tests and cleaner, more maintainable code.
Contents
2. Dependancies
Maven dependancis
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.20.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>5.20.0</version>
<scope>test</scope>
</dependency>These two libraries come handy.
mockito-coregives you the mocking abilities.mockito-junit-jupitergives you clean, idiomatic support in your JUnit 5 test classes (no need to manually init mocks).
3. Example : mock, when, then
import org.junit.Test;
import org.mockito.Mockito;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
public class AuthenticatorApplicationTest {
@Test
public void testAuthenticate() {
// Arrange
AuthenticatorInterface authenticatorMock;
AuthenticatorApplication authenticator;
String username = "JavaCodeGeeks";
String password = "unsafePassword";
authenticatorMock = Mockito.mock(AuthenticatorInterface.class);
authenticator = new AuthenticatorApplication(authenticatorMock);
when(authenticatorMock.authenticateUser(username, password))
.thenReturn(false);
// Act
boolean actual = authenticator.authenticate(username, password);
// Assert
assertFalse(actual);
}
}The key part is when we add the behavior, with the when() and thenReturn() functions. Is quite expressive: "When the mock object is called for this method with this parameters, then it returns this value". Note that we are defining the behavior in the mock object, not to the class calling the mock object.
As we are adding the behavior to the reference that has been passed to AuthenticatorApplication instance, it doesn’t matter if we first add the behavior and then we pass the reference, or reverse.
When the AuthenticatorApplication calls to its AuthenticatorInterface, it won’t know what is actually happening, the only thing it knows is just how to deal with the defined interface, which for this case has been designed to return false when it receives "JavaCodeGeeks" and "unsafePassword" as inputs.
Ref: https://www.javacodegeeks.com/wp-content/uploads/2016/09/Mockito-Programming-Cookbook.pdf
4. Verify that method has been called
We can check if a method has been called with certain parameters. For that, we would do something similar to the following:
AuthenticatorApplicationTest.java
// ...
verify(authenticatorMock).authenticateUser(username, password);
// ...To verify that authenticatorMock mock’s authenticateUser method, with username and password parameters.
Apart from checking that the method is actually being called, this verifications are useful to check that the parameters arrive to the method call as they are supposed to arrive. So, for example, if you run the test with the following verification:
AuthenticatorApplicationTest.java
// ...
verify(authenticatorMock).authenticateUser(username, "not the original password");
// ...The test will fail.
Ref: https://www.javacodegeeks.com/wp-content/uploads/2016/09/Mockito-Programming-Cookbook.pdf
4.1. Verify interactions and stub method calls
Verifying interactions..
import static org.mockito.Mockito.*;
// mock creation
List mockedList = mock(List.class);
// or even simpler with Mockito 4.10.0+
// List mockedList = mock();
// using mock object - it does not throw any "unexpected interaction" exception
mockedList.add("one");
mockedList.clear();
// selective, explicit, highly readable verification
verify(mockedList).add("one");
verify(mockedList).clear();and stub method calls
// you can mock concrete classes, not only interfaces
LinkedList mockedList = mock(LinkedList.class);
// or even simpler with Mockito 4.10.0+
// LinkedList mockedList = mock();
// stubbing appears before the actual execution
when(mockedList.get(0)).thenReturn("first");
// the following prints "first"
System.out.println(mockedList.get(0));
// the following prints "null" because get(999) was not stubbed
System.out.println(mockedList.get(999));Ref: https://site.mockito.org/
4.2. Verify that method has been called n times
Apart from checking that the method has been called or not, we have many possibilities regarding to number of method calls.
Let’s see how we can do it:
AuthenticatorApplicationTest.java
// ...
verify(authenticatorMock, times(1)).authenticateUser(username, password);
verify(authenticatorMock, atLeastOnce()).authenticateUser(username, password);
verify(authenticatorMock, atLeast(1)).authenticateUser(username, password);
verify(authenticatorMock, atMost(1)).authenticateUser(username, password);
// ...As you can see, we have different notations available to make the verifications: specifying the number of times that the mocking method should be called, how much times should be called at least, and how much at most.
As in the previous example, the verifications are made for the exact parameters that the mocking method uses.
We can also verify that the method has never been called:
AuthenticatorApplicationTest.java
// ...
verify(authenticatorMock, never()).authenticateUser(username, password); // This will make the test fail!
// ...Which, actually, is equivalent to times(0), but would be more expressive when we really want to verify that a method has never been called.
Ref: https://www.javacodegeeks.com/wp-content/uploads/2016/09/Mockito-Programming-Cookbook.pdf
5. More info
Main reference documentation features:
mock()/@Mock: create mock- optionally specify how it should behave via
Answer/MockSettings when()/given()to specify how a mock should behave- If the provided answers don’t fit your needs, write one yourself extending the
Answerinterface
- optionally specify how it should behave via
spy()/@Spy: partial mocking, real methods are invoked but still can be verified and stubbed@InjectMocks: automatically inject mocks/spies fields annotated with@Spyor@Mockverify(): to check methods were called with given arguments- Try Behavior-Driven development syntax with BDDMockito
- Use Mockito on Android, thanks to the team working on dexmaker
Ref: https://site.mockito.org/
6. Remember... !!
- Do not mock types you don’t own
- Do not mock value objects
- Do not mock everything
- Show love with your tests!
Click here for more documentation and examples. All documentation lives in javadocs so you don’t need to visit that page too often. There is also a RefCard.
If you have suggestions, find documentation unclear, or find a bug, write to our mailing list. You can report feature requests and bugs in GitHub.
Ref: https://site.mockito.org/
7. References
How to write good tests · mockito/mockito Wiki · GitHub https://github.com/mockito/mockito/wiki/How-to-write-good-tests
Mockito framework site https://site.mockito.org/
Mockito Programming Cookbook https://www.javacodegeeks.com/wp-content/uploads/2016/09/Mockito-Programming-Cookbook.pdf
Mockito vs EasyMock · mockito/mockito Wiki · GitHub https://github.com/mockito/mockito/wiki/Mockito-vs-EasyMock