An overview of

Mockito is a simulation framework for unit testing in Java.

Introduce POM dependencies

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-all</artifactId>
    <version>LATEST</version>
</dependency>
Copy the code

Enable Mockito

Create a mock object using the class argument (class, interface) that differs from the real object. Use a series of static methods of the Mockito class.

public static <T> T mock(Class <T> classToMock)
Copy the code

Write a Mockito example

Mockito relies on Junit.

package org.byron4j.cookbook.mocketio.basic;

import org.junit.Test;
import org.mockito.Mockito;

import java.util.ArrayList;
import java.util.List;

import static org.junit.Assert.assertEquals;

public class MockitoAnnotationTest {

    @Test
    public void whenNotUseMockAnnotation_thenCorrect(a) {
        // Create a mock ArrayList object
        List mockList = Mockito.mock(ArrayList.class);

        // Call the methods of the mock object
        mockList.add("one");
        //mockList.add("one");

        // Get the actual method of the mock object, and get the size, which results in 0
        System.out.println("mockList.size(): " + mockList.size());
        / / the toString method
        System.out.println("mockList's toString is: " + mockList);

        // Verify that the mockList object's add method is called once
        Mockito.verify(mockList).add("one");
        assertEquals(0, mockList.size());

        // Always return 100 when mockList.size() is called
        Mockito.when(mockList.size()).thenReturn(100);

        assertEquals(100, mockList.size()); }}Copy the code

The running output is:

mockList.size(): 0
mockList's toString is: Mock for ArrayList, hashCode: 409962262
Copy the code
  • useList mockList = Mockito.mock(ArrayList.class);Create a mock ArrayList object mockList
  • Call the methods of the mock objectmockList.add("one");
  • And then callmockList.size()The result is 0, indicating thatmockList.add("one");The code simply indicates that the Add behavior itself occurred and does not affect the other behaviors of mockList.
  • The verify method verifies that the add method of the Mock object mockList was called once
Mockito.verify(mockList).add("one");
assertEquals(0, mockList.size());
Copy the code
  • Mocklist.size () always returns 100 when called
Mockito.when(mockList.size()).thenReturn(100);
assertEquals(100, mockList.size());
Copy the code

verify

Verify (mock, times(1)), for example: verify(mock).somemethod (“some arg”); . Equivalent to verify(mock, times(1)).somemethod (“some arg”);

Mockito.verify(mockList).add("one");
Copy the code

Equivalent to

Mockito.verify(mockList, Mockito.times(1)).add("one");
Copy the code

Mockito.times(1) The argument 1 indicates that the number of times expected to be executed is 1.

The verify method takes two arguments: the mock object and the validation pattern
public static <T> T verify(T mock, VerificationMode mode);
Copy the code

Mockito. Times (int wantedNumberOfInvocations) be able to get a VerificationMode object, The actual call VerificationModeFactory. Times (wantedNumberOfInvocations) access to a times object: New Times (wantedNumberOfInvocations), Times VerificationMode interface is realized.

  • Parameter one: mock object, required

  • Parameter 2: Validation mode: times(x), atLeastOnce() or never(), etc. If times(1), ignore this parameter

The Times method call stack is as follows:

org.mockito.Mockito#times(int wantedNumberOfInvocations)
	org.mockito.internal.verification.VerificationModeFactory#times(int wantedNumberOfInvocations)
		org.mockito.internal.verification.Times(int wantedNumberOfInvocations)
Copy the code

Method the when

The Mockito. When method is defined as follows:

public static <T> OngoingStubbing<T> when(T methodCall)
Copy the code

The when method requires a call to a method of a mock object, such as in this case we passed a call to the mockList.size() method of the mock object mockList. The when method keeps a stub to call back when we want to simulate returning a particular return value in a particular case. The simple intent is that when the x method is called, it returns y.

Example:

  • when(mock.someMethod()).thenReturn(10); : returns 10 when a method is called

  • when(mock.someMethod(anyString())).thenReturn(10); : Flexible parameters

  • when(mock.someMethod(“some arg”)).thenThrow(new RuntimeException()); : Throws an exception when a method is called

  • when(mock.someMethod(“some arg”)).thenThrow(new RuntimeException()).thenReturn(“foo”); : Calls different behaviors consecutively

  • when(mock.someMethod(“some arg”)).thenReturn(“one”, “two”); : Continuous stub, the first call returns “one”, the second and subsequent calls return “two”

  • when(mock.someMethod(“some arg”)).thenReturn(“one”).thenReturn(“two”); : Same as above

  • when(mock.someMethod(“some arg”)).thenThrow(new RuntimeException(), new NullPointerException(); : Continuous stub, throw exception

@Test
public void whenTest(a) {
    List mock = Mockito.mock(List.class);
    Mockito.when(mock.size()).thenReturn(-1);
    System.out.println("mock.size():" + mock.size());



    // Continuous stub
    Mockito.when(mock.size()).thenReturn(1).thenReturn(2).thenReturn(3);
    for(int i=1; i <= 5; i++){
        System.out.println("===== continuous stub method 1: ===== :" + mock.size());
    }

    Mockito.when(mock.size()).thenReturn(1.2.3);
    for(int i=1; i <= 5; i++){
        System.out.println("##### continuous stub 2: ##### :" + mock.size());
    }

    // Simulate an exception
    Mockito.when(mock.size()).thenThrow(new RuntimeException(), new NullPointerException());
    try{
        mock.size();
    }catch (Exception e){
        System.out.println(e);
    }
    try{
        mock.size();
    }catch(Exception e){ System.out.println(e); }}Copy the code

Run output:

Mock. The size () : 1 = = = = = 1: continuous stub way = = = = = : 1 = = = = = 1: continuous stub way = = = = = : 2 = = = = = 1: continuous stub way = = = = = : 3 = = = = = 1: continuous stub way = = = = = : 3 continuous stub way = = = = = 1: = = = = = : 3 continuous stub method 2: # # # # # # # # # #, # # # # # 1 continuous stub way 2: # # # # #, 2 # # # # # for the stub method 2: # # # # #, 3 # # # # # continuous stub way 2: # # # # #, 3 # # # # # continuous stub way 2: # # # # # :  3 java.lang.RuntimeException java.lang.NullPointerExceptionCopy the code

Enable annotations on Mockito

@runWith (MockitoJUnitRunner. Class) Enable annotation

Use @RunWith(MockitoJUnitRunner.class) to enable Mockito annotations on classes.

@RunWith(MockitoJUnitRunner.class)
public class MockitoAnnotationStartup {}Copy the code

@ Mock annotations

Mock objects are available through the @mock annotation, which is equivalent to mockito.mock (class).

    /** annotate the mock object */
    @MockList<String> mockList; Equivalent to List<String> mock = mockito.mock (list.class);Copy the code

The following is an example:

package org.byron4j.cookbook.mocketio.basic;

import org.junit.Test;
import org.mockito.Mock;
import org.mockito.Mockito;

import java.util.List;

import static org.junit.Assert.assertEquals;

public class MockitoAnnoTest extends MockitoAnnotationStartup{

    /** annotate the mock object */
    @Mock
    List<String> mockList;

    @Test
    public void testRaw(a){
        List<String> mock = Mockito.mock(List.class);
        mock.add("one");
        mock.add("one");
        Mockito.verify(mock, Mockito.times(2)).add("one");

        Mockito.when(mock.size()).thenReturn(100);
        assertEquals(100, mock.size());


    }

    @Test
    public void testAnno(a){
        mockList.add("one");
        mockList.add("one");
        Mockito.verify(mockList, Mockito.times(2)).add("one");

        Mockito.when(mockList.size()).thenReturn(100);
        assertEquals(100, mockList.size()); }}Copy the code

@ Spy annotations

Similar to the @Mock annotation, there is also the @Spy annotation. I don’t have a spy on you.

List<String> mock = Mockito.spy(List.class);
Copy the code

Using annotations

@Spy
List<String> spyList;
Copy the code

Captor annotation (parameter catcher)

The argument catcher ArgumentCaptor corresponds to the @captor annotation.

Create a parameter catcher in the original way:

@Test
public void whenNotUseCaptorAnnotation_thenCorrect(a) {
    List mockList = Mockito.mock(List.class);
    ArgumentCaptor<String> arg = ArgumentCaptor.forClass(String.class);
 
    mockList.add("one");
    Mockito.verify(mockList).add(arg.capture());
 
    assertEquals("one", arg.getValue());
}
Copy the code

Create a parameter catcher using the @captor annotation:

@Mock
List mockedList;
 
@Captor
ArgumentCaptor argCaptor;
 
@Test
public void whenUseCaptorAnnotation_thenTheSam(a) {
    mockedList.add("one");
    Mockito.verify(mockedList).add(argCaptor.capture());
 
    assertEquals("one", argCaptor.getValue());
}
Copy the code
  • ArgumentCaptor<String> arg = ArgumentCaptor.forClass(String.class);: Creates a parameter catcher
  • Mockito.verify(mockedList).add(argCaptor.capture());: Use a catcher to capture the parameters of the method add in a validation; The capture method must be in a validation.
  • argCaptor.getValue(): Gets the parameter captured by the parameter catcher

@ InjectMocks annotations

The @injectMocks annotation can automatically inject the properties of the mock into the test object.

@Mock
Map<String, String> wordMap;

@InjectMocks
MyDictionary myDictionary = new MyDictionary();


@Test
    public void testInjectMocks(a){
        Mockito.when(wordMap.get("aWord")).thenReturn("aMeaning");

        assertEquals("aMeaning", myDictionary.getMeaning("aWord"));

        System.out.println(myDictionary.getMeaning("aWord"));
    }

    class MyDictionary{
        Map<String, String> wordMap;

        public String getMeaning(String word){
            returnwordMap.get(word); }}Copy the code
  • MyDictionary class has the attribute wordMap:Map<String, String> wordMap;
  • Mock a variable named wordMap:
@Mock
Map<String, String> wordMap;
Copy the code
  • Using the @injectMocks annotation:
@InjectMocks
MyDictionary myDictionary = new MyDictionary();
Copy the code

The mock wordMap object is injected into the property of the same name of the myDictionary instance.

Notes:

Use annotations to minimize the repetition of writing code to create mock objects

Use annotations to make test cases more readable

Inject @Spy and @Mock objects with @InjectMocks annotations

References:

  • Mockito website: static. The javadoc. IO/org. Mockito…