使用来自mockito-junit-jupiter的MockitoExtension在构造函数测试类中进行空模拟

dav*_*xxx 5 java mockito junit5

通过使用@MockitoExtensionfrom 的扩展mockito-junit-jupiter,测试类构造函数中的模拟为 null。

使用的依赖项:

模拟-junit-jupiter:2.18.0
单元-jupiter-api:5.1.1

我们可以仅使用模拟字段来重现该问题,但测试对象构造函数对模拟的使用很好地说明了典型场景:

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
public class FooTest {

    @Mock
    Bar mockBar;
    Foo foo;

    public FooTest() {
        foo = new Foo(mockBar); // mockBar is null here
    }

    @Test
    public void doThis() {
        Mockito.when(mockBar.doThat())
               .thenReturn(Mockito.anyInt());
        // ...
    }

}
Run Code Online (Sandbox Code Playgroud)

结果,模拟对象四处走动,但不与Foo被测对象关联。
为什么 ?使用什么解决方法?

dav*_*xxx 5

解决方案1:

将构造函数初始化替换为@InjectMocks

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.InjectMocks;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
public class FooTest {

    @Mock
    Bar mockBar;

    @InjectMocks
    Foo foo;    

    @Test
    public void doThis() {
        Mockito.when(mockBar.doThat())
               .thenReturn(Mockito.anyInt());
        // ...
    }

}
Run Code Online (Sandbox Code Playgroud)

这可行,但使用@InjectMocks也是一个品味问题,因为如果所有注入策略都失败,那么 Mockito 将不会报告失败。
这种不需要的注射可能会让您烦恼。如果是这种情况,您可以使用下一种方法。

解决方案2:

将构造函数初始化替换为带有注释的方法@BeforeEach

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
public class FooTest {

    @Mock
    Bar mockBar;
    Foo foo;

    @BeforeEach
    public void beforEach() {
        foo = new Foo(mockBar); 
    }

    @Test
    public void doThis() {
        Mockito.when(mockBar.doThat())
               .thenReturn(Mockito.anyInt());
        // ...
    }

}
Run Code Online (Sandbox Code Playgroud)

  • 我根本不认为后一种解决方案是_解决方法_。这正是 @BeforeEach 存在于木星的原因。 (2认同)