为什么我在使用 PowerMockRunner 运行时不能使用 @InjectMocks 字段匹配?

我遇到了一个问题,在有 2 个 的情况下,匹配 Mockito 的 @Mock 注释的字段注入 @InjectMocks 不起作用>@Mock 的相同类型.我也使用了 @Mock (name = "name_of_var") 语法,但仍然失败...

I've run into an issue in which the field injection matching for Mockito's @Mock annotation for @InjectMocks is not working in the case where there are 2 @Mocks of the same type. I've used the @Mock (name = "name_of_var") syntax as well, but it still failed...

这是被测试的类:

    import java.util.Date;
    public class Parent{

    private Date dateA;
    private Date dateB;

    public void setDateA(Date _dateA){
       dateA = _dateA;
    }

    public void setDateB(Date _dateB){
       dateB = _dateB;
    }

    public Date getDateA(){
       return dateA;
    }

    public Date getDateB(){
       return dateB;
    }

这是测试本身:

    @RunWith(PowerMockRunner.class)
    @PrepareForTest({System.class, Parent.class})
    public class testParent{

    @Mock (name = "dateB")  private Date someOtherDate;
    @Mock (name = "dateA")  private Date someDate;    

    @InjectMocks Parent p;

    @Before
    public void setup(){
        Mockito.when(someOtherDate.getTime()).thenReturn(500l);
        PowerMockito.mockStatic(System.class);
        PowerMockito.when(System.currentTimeMillis()).thenReturn(2000l);
    }

    @Test
    public void testGetDateAGetTimeShouldReturn1000() {
        Mockito.when(someDate.getTime()).thenReturn(1000l);
        Date result = p.getDateA();
        assertEquals(1000l, result.getTime());
    }

    @Test
    public void testGetDateBGetTimeShouldReturn500() {
        Date result = p.getDateB();
        assertEquals(500l, result.getTime());   
    }

测试时,由于 @InjectMocks 不起作用,两个 assertEquals 都会导致 NullPointerException.

When tested, both assertEquals cause a NullPointerException due to the fact that the @InjectMocks did not work.

现在,当我将 @RunWith(PowerMockRunner.class) 替换为 @RunWith(MockitoJUnitRunner.class) 时,它工作得很好.

Now, when I replaced @RunWith(PowerMockRunner.class) with @RunWith(MockitoJUnitRunner.class), it WORKS just fine.

另外,如果我刚刚在 Parent.java 中定义了 1 个 Date 变量(例如 dateA )和一个要注入的匹配模拟ParentTest,使用 PowerMockRunner.class 注入就好了.

Also, if I had just defined 1 Date variable ( say, dateA ) in Parent.java and a matching mock to inject in ParentTest, it would inject just fine using PowerMockRunner.class.

我必须使用 PowerMockRunner.class 运行的原因是我必须能够模拟静态函数以及构造函数.

The reason I must run with PowerMockRunner.class is because I must be able to mock static functions as well as constructors.

我正在使用 Junit4.12、Mockito-all-1.10.19 和 PowerMock-mockito-1.6.2-full 运行.

I am running with Junit4.12, Mockito-all-1.10.19, and PowerMock-mockito-1.6.2-full.

有没有人看到为什么它没有正确注入 PowerMockRunner.class 的原因?使用 PowerMockRunner.class 运行时是否有解决方法?

Does anyone see the cause of why it does not inject properly with PowerMockRunner.class? Is there a workaround for this while running with PowerMockRunner.class?

推荐答案

如果你要使用PowerMockRunner,你必须调用MockitoAnnotations.initMocks() 以初始化模拟使用注释创建的.

If you are going to use PowerMockRunner, you have to call MockitoAnnotations.initMocks() in order to initialize the mocks that are created using the annotations.

然而,根本不使用 InjectMocks 有几个很好的理由.一般来说,您对如何设置测试的控制较少.最好只调用 new 并手动传递参数.此外,如果有任何问题,Mockito 只会默默地失败.在这篇文章中查看更多内容:

However, there are several good reasons not to use InjectMocks at all. Generally speaking, you have less control over how your test is set up. It's better to just call new and pass the arguments in manually. Also, if there's any sort of a problem Mockito will just fail silently. See more in this article:

Mockito 将尝试仅通过构造函数注入、setter 注入或属性注入按顺序注入模拟,如下所述.如果以下任一策略失败,则 Mockito 不会报告失败;即您必须自己提供依赖项.

Mockito will try to inject mocks only either by constructor injection, setter injection, or property injection in order and as described below. If any of the following strategy fail, then Mockito won’t report failure; i.e. you will have to provide dependencies yourself.

相关文章