Junit Mockito and Power Mockito

Mock vs Spy

Both can be used to mock methods or fields. The difference is that in mock, you are creating a complete mock or fake object while in spy, there is the real object and you just spying or stubbing specific methods of it.

Mock vs InjectMock

@Mock creates a mock. @InjectMocks creates an instance of the class and injects the mocks that are created with the @Mock (or @Spy) annotations into this instance.

Unit Testing Void Methods with Mockito and JUnit

How to Test Void Methods 

As we already know that our aim is to test void methods in a class. But it is also really important to understand why we test void methods. 

Whenever we write unit test cases for any method, we expect a return value from the method. Generally, we use assert for checking if the method returns the value that we expect it to return, but in the case of void methods, they do not return any value. So how do we check if our method is functioning properly? Let’s see using an example:

In this example, we are creating two classes: Informationand Publishing.

TheInformationclass looks like this:

public class Information {
2
3
   private final Publishing publishing;
4
5
   public Information(Publishing publishing) {
6
       this.publishing = publishing;
7
   }
8
9
   public void sendInfoForPublishing(Person person) {
10
       publishing.publishInformation(person);
11
   }

12
}

As we can see, the methodsendInformationForPublishing()is a void method. The logic for the method is simple. It takes a Personobject as a parameter and passes the object to the method of thePublishingclass.

The method publishInformation()is also a void method.

public class Publishing {
2
3
   public void publishInformation(Person person) {
4
       System.out.println(person);
5
   }
6
}

Using the verify()Method

Whenever we mock a void method, we do not expect a return value. That is why we can only verify whether that method is being called or not. 

Features of verify():

Mockito provides us with a verify()method that lets us verify whether the mock void method is being called or not. 

It lets us check the number of methods invocations. So, if the method invocation returns to be zero, we would know that our mock method is not being called.

verify(publishing,times(1)).publishInformation(person);

The verify method takes two arguments. The mock method object and the number of invocations you want to verify. The expected number of invocations is passed in the times()method. Let’s see how the test case will look:

public class InformationTest {
2
3
   Publishing publishing = mock(Publishing.class);
4
5
   @Autowired
6
   private Information information;
7
8
   @Test
9
   void whenSendInformationForPublishingIsSuccessful() {
10
       information = new Information(publishing);
11
       Person person = ObjectCreator.getPerson();
12
       doNothing().when(publishing).publishInformation(person);
13
       information.sendInfoForPublishing(person);
14
       verify(publishing,times(1)).publishInformation(person);
15
   }
16
}

As our function will callpublishInformation()only once, so we have passed the value 1 in the times()function. We know that when our test case will call the mocked publishInformation()method, it will not do anything. We need to let Mockito know of this behavior. For this, we use thedoNothing()method, which will, in simple terms, let Mockito know that it needs to do nothing when the given method is called.

If we change the number of invocations to any other value, the test case should fail.

Mocking Static Methods With Mockito

When writing tests, we'll often encounter a situation where we need to mock a static method. Previous to version 3.4.0 of Mockito, it wasn't possible to mock static methods directly — only with the help of PowerMockito.

A Simple Static Utility Class

public class StaticUtils { private StaticUtils() {} public static List<Integer> range(int start, int end) { return IntStream.range(start, end) .boxed() .collect(Collectors.toList()); } public static String name() { return "Baeldung"; } }

A Quick Word on Testing Static Methods

Generally speaking, some might say that when writing clean object-orientated code, we shouldn't need to mock static classes. This could typically hint at a design issue or code smell in our application.

Why? First, a class depending on a static method has tight coupling, and second, it nearly always leads to code that is difficult to test. Ideally, a class should not be responsible for obtaining its dependencies, and if possible, they should be externally injected.

So, it's always worth investigating if we can refactor our code to make it more testable. Of course, this is not always possible, and sometimes we need to mock static methods.

Mocking a No Argument Static Method

@Test void givenStaticMethodWithNoArgs_whenMocked_thenReturnsMockSuccessfully() { assertThat(StaticUtils.name()).isEqualTo("Baeldung"); try (MockedStatic<StaticUtils> utilities = Mockito.mockStatic(StaticUtils.class)) { utilities.when(StaticUtils::name).thenReturn("Eugen"); assertThat(StaticUtils.name()).isEqualTo("Eugen"); } assertThat(StaticUtils.name()).isEqualTo("Baeldung"); }

Mocking a Static Method With Arguments

@Test void givenStaticMethodWithArgs_whenMocked_thenReturnsMockSuccessfully() { assertThat(StaticUtils.range(2, 6)).containsExactly(2, 3, 4, 5); try (MockedStatic<StaticUtils> utilities = Mockito.mockStatic(StaticUtils.class)) { utilities.when(() -> StaticUtils.range(2, 6)) .thenReturn(Arrays.asList(10, 11, 12)); assertThat(StaticUtils.range(2, 6)).containsExactly(10, 11, 12); } assertThat(StaticUtils.range(2, 6)).containsExactly(2, 3, 4, 5); }

Here, we follow the same approach, but this time we use a lambda expression inside our when clause where we specify the method along with any arguments that we want to mock.

True utility static classes do not need to be mocked because their output is always deterministic depending on 1.their inputs.

Junit Assert Methods

1.assertTrue(condition)

2.assertFalse(condition)

3.assertNull(object)

4.assertNotNull(object)

5.assertSame(expected, actual)

6.assertNotSame(expected, actual)

7.assertEquals(a,b)


Why do we need mocking?

There are a lot of use cases of mocking that aid in unit testing of the code under isolation and make the test highly repeatable and predictable.

Mocking is generally required when :

a) The component under test has dependencies that are not yet implemented or the implementation is in progress.

A good example can be a REST API endpoint which will be available later at some point in time, but you have consumed it in the code via a dependency.

Now as the real implementation is still not available,  you really know most of the time what is the expected response of that API. Mocks allow you to test those kinds of integration.

b) Component updates the state in the system.

Example: DB calls – you would not want to update your DB with data that is just for testing purposes. This might result in corrupting the data, moreover, the availability of DB is another challenge when the test is executed.

Thus to avoid such behavior, DB calls could be mocked in the component under test. Hence there is no direct coupling of DB and the component under test.

When and why should a spy be used?

Spy is a type of partial mock supported by Mockito.

This essentially means is a type of instance where:

a) When no mock is setup, any interaction on spy results in calling the real methods. But it still allows you to verify the interactions with the spied object like – was a method actually called, how many times the method was called, what were the arguments using which the method was called etc.

b) It gives you the flexibility to set up partial mocks.

For Example, if you have an object with 2 methods – method1 and method2 and you want method1 to be called and method2 to be mocked. Spies provide this kind of setup.

So, the difference between a mock and a stub in simple terms is – a mock is created from a type and not from an instance whereas a stub wraps an actual instance of the class object.

Difference between doReturn and thenReturn.

The thenReturn way of stubbing is a type-safe way of setting up stubs. What this essentially means is that it does a compile-time check against the return types that you want to stub too.

// works

when(mockedItemService.getItemDetails(123)).thenReturn(new ItemSku());

// throws compile time exception

when(mockedItemService.getItemDetails(123)).thenReturn(expectedPrice);

// with doReturn,  both the stub setup works as it’s not compile safe.

// here we are trying to return an object of type double which still works and does not throw any compile time warning.

doReturn(expectedPrice).when(mockedItemService.getItemDetails(123));

doReturn(new ItemSku()).when(mockedItemService.getItemDetails(123));


What are the limitations of Mockito?

Mockito is a framework of choice for most of the java based projects. It is easy to implement, read and understand.

Some of the drawbacks or limitations in terms of functionality are:

1.Its inability to mock static methods.

2.Constructors, private methods and final classes cannot be mocked.


Which frameworks can support mocking Private and Static methods?

Frameworks like PowerMockito (extensions of Mockito framework), JMockit, etc. do provide means to mock private and static methods.


Returning multiple values against consecutive method calls

To return different values for multiple invocations of the same stubbed method, Mockito provides 3 approaches as given below:

a) Using comma separated: This works with thenReturn.

For Example, taking the above code sample, let us try to setup consecutive stub for method – getGrade which will return different values depending on the sequence of iterations:

when(mockDatabaseImpl.getGrade(anyInt())).thenReturn("A","B", "C");

This means that when getGrade methods get called in the method under test, the first invocation will return “A”, the second invocation will return “B” and so on.

b) Consecutive thenReturn: This is an approach that is chained with thenReturn statements. Applying chained calls to the same example will look as shown below.

when(mockDatabaseImpl.getGrade(anyInt())).thenReturn("A").thenReturn("B").thenReturn("C");

c) Consecutive doReturn: The last approach is using doReturn in the chained format as above.

doReturn("A").doReturn("B").doReturn("C").when(mockDatabaseImpl).getGrade(anyInt())


Comments

Popular posts from this blog

Java 8 : Find the number starts with 1 from a list of integers

Optional Vs Null Check

How to prevent Singleton Class from Reflection and Serialization