Using Mockito to create Java Unit Test

Category

Blog
1 December, 2020 0

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:

Explanation:

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

Add behavior to mock object

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:

Mockito.when(classMock.someMethod()).thenReturn(someValue);

Another way to do it would be:

Mockito.doReturn(someValue).when(classMock).someMethod();

How do we mock an object that does not return any value?

Mockito.doNothing().when(someObject).someMethod(arg);

What things can I test

Check if a method was not invoked:

verify(service, never()).calculateX();

If the method was invoked n times:

verify(service, times(n)).calculateX()

If the method was invoked with the value x:

verify(service).calculateY(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.

How to initialize a class

When we use a class depending on the use we are going to give it, we can initialize it in different ways.

  • Initialize it as we always do, for example:

     User user = new User();
  • A good practice would be to create a Builder class and do something like this:
     User user = UserBuilder.standard().build();
  • Finally if we need to create a Mock of the class we do it like this:
     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.

Mock method same class – @Spy

To exemplify it, suppose we now have the class MyClass, where the calculateY method instead of being part of MyService is part of MyClass.

This line:

    when(myClass.calculateY(1)).thenReturn(2);

It will give me the error:

    exceptions.misusing.MissingMethodInvocationException:
    when() requires an argument which has to be 'a method 
    call on a mock'.

Solution:

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:

     Mockito.doReturn(false).when(spyClass).isActive();

In this case, the real method will be invoked:

     Mockito.when(spyClass.isActive()).thenReturn(false);

Provide argument matcher

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:

     when(service.calculateY(Mockito.anyInt())).thenReturn(2);

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("test@email.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:

Solution:

     Mockito.verify(ServiceName, times(1)).functionName(Mockito.eq("test@email.com"),any());

Or

     Mockito.verify(ServiceName, times(1)).functionName("test@email.com","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

COMMENTS

Leave a Reply

Your email address will not be published. Required fields are marked *

Karien Debia
Karien Debia
Computer Analyst
Tuesday December 1, 2020 - 01:12 Blog , , ,
Recent posts
Using Mockito to create Java Unit Test

Let’s start with the definition given by the official page. “Mockito is a mocking framework that tastes really good. It […]

Read More…

Continue reading
1 December, 2020
From idea to deploy

When the great idea and background just isn’t enough […]

Read More…

Continue reading
11 August, 2020
Reclaim your disk space from Xcode

Do you have problems with the space on your disk? You are in the right place! This post is for […]

Read More…

Continue reading
25 June, 2020
RoR – Get your exceptions notified via Slack

Have you ever wanted to be one step ahead, and be notified of any unwanted exception before your users have […]

Read More…

Continue reading
18 October, 2018