Mockito,@InjectMocks 最终字段的奇怪行为

2022-01-14 00:00:00 mockito java testng

我看到我认为是错误的行为.@InjectMocks 似乎并没有在每个测试方法之前创建一个新的测试主题.@Mock 在哪里.在以下示例中,如果 Subject.section 是最后一个 @Test 失败.如果它不是最终的,则两者都通过.我目前的解决方法是使用@BeforeClass,但这并不理想.

I am seeing behaviour that I believe is a bug. @InjectMocks does not seem to create a new test subject before every test method. Where as @Mock does. In the following example, if Subject.section is final one @Test fails. If its not final both pass. My current workaround is to use @BeforeClass, but this is not ideal.

主题.java:

package inject_mocks_test;
public class Subject {

    private final Section section;

    public Subject(Section section) {
        this.section = section;
    }

    public Section getSection() {
        return section;
    }
}

Section.java:

Section.java:

package inject_mocks_test;

public class Section {}

SubjectTest.java

SubjectTest.java

package inject_mocks_test;

import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import static org.testng.Assert.assertEquals;

public class SubjectTest {

    @Mock
    Section section;

    @InjectMocks
    Subject subject;

    @BeforeMethod
    public void setup() {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void test1() {
        assertEquals(section, subject.getSection());
    }

    @Test
    public void test2() {
        assertEquals(section, subject.getSection());        
    }
}

干杯.

推荐答案

您正在使用 @InjectMocks 进行 constructor 注入.只要 Mockito 找到未初始化的字段(空),这将起作用.JUnit 在每次测试之前都会创建一个新的测试类实例,所以 JUnit 粉丝(像我一样)永远不会遇到这样的问题.TestNg 没有创建测试类的新实例.它保持测试方法之间的状态,所以当 MockitoAnnotations.initMocks(this) 第二次调用时,Mockito 会发现 subject 字段已经初始化并尝试使用 <强>场注入.这在另一回合将一直有效,直到该领域不是最终的.

You are using the @InjectMocks for constructor incjection. This will work as long as Mockito finds the field not initalized (null). JUnit is creating a new instance of the test class before each test, so JUnit fans (like me) will never face such problem. TestNg is not creating a new instance of test class. It's keeping the state between test methods, so when MockitoAnnotations.initMocks(this) is called for the second time, Mockito will find subject field already initialized and will try to use field injection. This on the other turn will work until the field is not final.

这是一个错误吗?我相信不是——而是 API 设计的自然结果.一些解决方法是添加

Is this is a bug? I believe not - rather a natural consequence of the API design. Some workaround for you would be to add

this.subject = null;

在一些 @AfterMethod 方法中.

相关文章