Welcome to the Mockito post, which in a quick and practical way, will help you understand how to use Mockito and will give you the lines of code, tools and possible errors you need to know, so that before you know it, you can be generating your own tests.
Let’s start with the definition given by the official page.
“Mockito is a mocking framework that tastes really good. It lets you write beautiful tests with a clean & simple API. Mockito doesn’t give you hangover because the tests are very readable and they produce clean verification errors.”https://site.mockito.org/
The first step is to declare the dependency to the library to use it. https://search.maven.org/artifact/org.mockito/mockito-core
For example with Maven it would be:
<dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <version>1.10.19</version> </dependency>
The basic idea of these tests is to isolate what we want to test from all the rest, for this what we do is generate Mock Objects. A Mock object, mocking (imitate the behavior of) the real service, returns dummy data that we indicate.
Probably the best way to understand how this works is to go directly to an example.
So, let’s imagine we have this class and this service.
We isolate the calculateZ method which is the one we want to test and mock the other methods, so the test would look like this:
@Mock creates a mock.
@InjectMock creates an instance of the class and injects the mocks that are marked with the annotations @Mock into it.
@Before this method will be executed before the test method.
@Test indicates that the method is a test.
MockitoAnnotations.initMocks(this) initializes fields annotated with Mockito annotations.
In order to isolate our method, we “assume” that the other methods work well and for that we mock their behavior making it return the expected value.
We do it with the following line of code:
Another way to do it would be:
How do we mock an object that does not return any value?
Check if a method was not invoked:
If the method was invoked n times:
If the method was invoked with the value x:
Other tags we can use are:
atLeastOnce(), atLeast(n), atMost(n)
And of course we can compare the results, using for example:
assertEquals(expectedValue, actualValue); assertNotEquals(unexpected, actual) assertNotNull(actual); assertTrue(condition) – assertFalse(condition)
How do I test if the expected result can have more than one valid option?
assertThat(result, isOneOf("value1", "value2"));
Now that we understand the basics and we know how it works, let’s see some more details that will be useful when creating our Unit tests.
When we use a class depending on the use we are going to give it, we can initialize it in different ways.
User user = new User();
User user = UserBuilder.standard().build();
User mockUser = Mockito.mock(User.class);
Remember that the method “when()” requires an argument which has to be a method call on a mock. Also the verify method applies only to Mocks.
To exemplify it, suppose we now have the class MyClass, where the calculateY method instead of being part of MyService is part of MyClass.
It will give me the error:
exceptions.misusing.MissingMethodInvocationException: when() requires an argument which has to be 'a method call on a mock'.
use @Spy tag like this:
@InjectMocks @Spy private MyClass myClass;
An important difference between the Spy and Mock classes is that we previously saw that there are 2 ways to add behavior to a Mock.
In Mock’s case, the actual method is never called.
But in the case of @Spy there is an important difference here, since in one case the real method is NOT called and in the other it is. Let’s see an example.
In this case the real method is NOT invoked:
In this case, the real method will be invoked:
Sometimes maybe we just don’t care about the actual value being passed as an argument, so in those cases we can use some of the following argument matchers:
anyString(), anyInt(), anyBoolean(), any(), any(Date.class)
So in our previous example instead of passing the value 1 to the calculateY method we can do the following:
Something to keep in mind here is that it cannot be mixed with real values.
For example this line of code:
Mockito.verify(ServiceName, times(1)).functionName("email@example.com", any());
If we run it as JUnit test in Eclipse, we can see that the Junit view Console shows us the following error message:
Mockito.verify(ServiceName, times(1)).functionName("firstname.lastname@example.org","real name");
Another aspect that we can notice here is that Mockito shows a good error message including even possible solutions. So pay attention to the error messages.
So as we have seen, Mockito allows us to easily isolate our classes so that we can test them without worrying about the other modules.
The only thing left is to generate your test code, Mock what you need to Mock, invoke the method and verify that the result is what you expected!www.freepik.es