跳至主要內容

Mockito Note

Scarb大约 2 分钟

原文地址:http://hscarb.github.io/java/20230815-mockito-note.htmlopen in new window

Mockito Note

https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/open in new window

https://github.com/eugenp/tutorials/tree/master/testing-modules/mockito-simpleopen in new window

difference between doReturn() and when()open in new window

In the case of mocked objects, it does not matter if it's when/thenReturn or doReturn/when. Mocked objects never calls real methods.

Both approaches behave differently if you use a spied object (annotated with @Spy) instead of a mock (annotated with @Mock):

  • when(...) thenReturn(...) makes a real method call just before the specified value will be returned. So if the called method throws an Exception you have to deal with it / mock it etc. Of course you still get your result (what you define in thenReturn(...))
  • doReturn(...) when(...) does not call the method at all.

Difference between @Mock and @InjectMocksopen in new window

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

Note you must use @RunWith(MockitoJUnitRunner.class) or Mockito.initMocks(this) to initialize these mocks and inject them (JUnit 4).

With JUnit 5, you must use @ExtendWith(MockitoExtension.class).

mock singleton

@RunWith(MockitoJUnitRunner.Silent.class)
public class Test {

    @Mock
    Singleton singleton;
    
    @Before
    public void setUp() throws Exception {
        setUpSingletons();
    }
    
    @After
    public void tearDown() throws Exception {
        resetSingletons();
    }
    
    private void setUpSingletons() throws Exception {
        final Field instance = Singleton.class.getDeclaredField("instance");
        instance.setAccessible(true);
        instance.set(instance, singleton);
    }
    
    private void resetSingletons() throws Exception {
        final Field instance = Singleton.class.getDeclaredField("instance");
        instance.setAccessible(true);
        instance.set(instance, null);
    }
    
    @Test
    public void test() {
        // ...
    }
}

Mocking Exception Throwingopen in new window

Non-Void Return Type

First, if our method return type is not void, we can use when().thenThrow():

@Test
void givenNonVoidReturnType_whenUsingWhenThen_thenExceptionIsThrown() {
    MyDictionary dictMock = mock(MyDictionary.class);
    when(dictMock.getMeaning(anyString())).thenThrow(NullPointerException.class);
    
    assertThrows(NullPointerException.class, () -> dictMock.getMeaning("word"));
}

Void Return Type

If our method returns void, we'll use doThrow():

@Test
void givenVoidReturnType_whenUsingDoThrow_thenExceptionIsThrown() {
    MyDictionary dictMock = mock(MyDictionary.class);
    doThrow(IllegalStateException.class).when(dictMock)
        .add(anyString(), anyString());
    
    assertThrows(IllegalStateException.class, () -> dictMock.add("word", "meaning"));
}

Checked Exceptionopen in new window

A workaround is to use a willAnswer()open in new window method.

For example the following works (and doesn't throw a MockitoException but actually throws a checked Exception as required here) using BDDMockito:

given(someObj.someMethod(stringArg1)).willAnswer( invocation -> { throw new Exception("abc msg"); });

The equivalent for plain Mockito would to use the doAnswer method

Mocking Static Methodsopen in new window

https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html#static_mocksopen in new window

When using the inline mock makeropen in new window, it is possible to mock static method invocations within the current thread and a user-defined scope. This way, Mockito assures that concurrently and sequentially running tests do not interfere. To make sure a static mock remains temporary, it is recommended to define the scope within a try-with-resources construct. In the following example, the Foo type's static method would return foo unless mocked:

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");
}

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);
}

欢迎关注公众号【消息中间件】(middleware-mq),更新消息中间件的源码解析和最新动态!