Mockito understanding and important keywords

Mockito comes with different annotation, out of them most used are below with their usage

1. @Mock :

Mock annotation is used to create Mocked instance. This are not real objects, rather created mock for class. @Mock annotation is same as

@RunWith(MockitoJUnitRunner.class)
public class MockTest {

@Mock
private List<String> list = new ArrayList<>();

@Test
public void testMock(){

//calling method on mock object, do nothing
list.add("first");
Assert.assertNull(list.get(0));
}
@Test
public void testMockWithStub() {
//try stubbing a method
String expected = "Mock String";
Mockito.when(list.get(0)).thenReturn(expected); Assert.assertEquals(expected, list.get(0));
}
}

2 @Spy :

Spy annotation is used to create real object and spy on that real object. With Spy, we are able to call all normal methods on spy object additionally can get behaviour of mock for whatever method we want.

@RunWith(MockitoJUnitRunner.class)
public class SpyTest {

@Spy
private List<String> list = new ArrayList<>();

@Test
public void testSpy(){

//call real method if not stub
list.add("first");
Assert.assertNotNull(list.get(0));
}
@Test
public void testSpyWithStub() {
//stubbing spy method will result same as mock object
String expected = "Spy String";
Mockito.doReturn(expected).when(list).get(0);
Assert.assertEquals(expected, list.get(0));
}
}

3 @InjectMocks:

During test, sometime it is required to create object of class which has dependent class which also needs to be mocked for some or other reason. annotation allows us to inject mocked dependencies in the annoted class.

Mockito tried to inject dependencies using 3 approch.

  • Constructor based injection
  • Setter method based injection
  • Field based injection

Here we are demonstration field based injection.

class A {
public String methodA(){
// do something
}
}
...class B { @Autowired
A a ;
public String methodB(){
return a.methodA();
}
}

Test class will look something like this:

@RunWith(MockitoJUnitRunner.class)
class Test {

@Mock
A a;
@InjectMocks
B b; // this will inject mock A in B
@Test
public void test(){
when(a).methodA().thenReturn("Test Method");
assertEquals("Test Method", b.methodB());
}
}

This annotation is used when we have external dependencies & we need to move behaviour of some external class or method.

Verify method

Mockito verify method will verify method invocation on mocked object. Method syntex of verify method is

  • .

Verification Modes:

Possible implementation of VerificationModes are

  • — verify mumber of interaction i.e will verify method called 1 time.
  • — Verify no invocation of method
  • — Verify min invocation of method
  • — Verify max invocation of method
  • — Verify only method invoked on object

Other verification methods.

VerificationAfterDelay is a that allows combining existing verification modes with an initial delay.

VerificationWithTimeout is a that allows combining existing verification modes with 'timeout'.

  • - Verify method Invocation 2 times after 100 ms delay
  • - Verify method Invocation 2 times in timeout period

Difference between and is — after will wait for full period, timeout will pass immediately if condition matched.

InOrder verification :

interface is useful to verify order of method invocation on mock object.

mock.method1();
mock.method2();
Inorder inOrder = inOrder(mock);inOrder.verify(mock).method1();
inOrder.verify(mock).method2();
inOrder.verifyNoMoreInteractions();

Method Argument matcher

This can be used during and method call.

  • Verify with exact argument : i.e.
  • Verify with flexible argument using ArgumentMatcher: i.e.
  • Verify with argument capture i.e using @Captor annotation

Argument matcher

Argument matcher are used for flexibile verfication and stubbing. It contains verifty of methods. few are:

  • anyXXX() — for matching any object type like anyInt(),anyString() etc
  • xxxThat() — For custom argument matcher
  • Manuplication methods like: eq(), contains(), endsWith() etc.
  • Logical ops like: or(),and(), not()
// anyXXX 
verify(mock).method1(anyObject());
verify(mock).method2(anyString(), anyInt());// argThat using java 8 lambda
verify(mock).method3(argThat -> { s -> s.length == 5 })
// eq method
verify(mock).method4(eq("test"))

It is not possible to use ArgmentMatcher only for some of the argument

// This will throw exception 
verify(mock).method5("test", anyInt());
// To make it work
verify(mock).method5(eq("test"), anyInt());

Matchers can be used as return values and can’t be used outside of stubbing.

Argument capture : @Captor annotation

Captor annotation is used to capture arguments of method. It create an instance of which is used in to verify arguments passed into method.

Captured arguments can be from and method. First one will return last value, later will return list if method call multiple times.

class StringTestUtils{
public boolean isEmpty(String s){
return s != null && !"".equals(s);
}
}
...
@RunWith(MockitoJUnitRunner.class)
public class CaptorTest {
@Mock
private StringTestUtils stringTestUtils;
@Captor
private ArgumentCaptor<String> captor;
@Test
public void testCaptor(){
stringTestUtils.isEmpty("test");
Mockito.verify(stringTestUtils).isEmpty(captor.capture());// getValue will return last value
Assert.assertEquals("test", captor.getValue());
}
@Test
public void testCaptor2(){
stringTestUtils.isEmpty("test");
stringTestUtils.isEmpty("test1");
verify(stringTestUtils,times(2)).isEmpty(captor.capture());// getAllValues will return all the values
Assert.assertEquals(2, captor.getAllValues().size());
Assert.assertEquals(List.of("test","test1), captor.getAllValues());
}
}

Traveller, Explorer, Curious to learn new things