java – 在@Rule之前通过@Mock初始化模拟

我有一个测试类,它正在测试Dropwizard资源并使用JUnit测试规则ResourceTestRule.它设置了许多模拟,我想替换这个成语:

Foo foo = mock(Foo.class);

这有点冗长

@Mock Foo foo;

但是Dropwizard ResourceTestRule需要像这样引用这些模拟

@Rule
public ResourceTestRule resources = ResourceTestRule.builder()
        .addResource(new BarResource(foo))
        .build();

我的问题是@Rule在@Mock初始化模拟之前运行,因此当实例化BarResource时foo为null,然后我在测试运行时得到空指针异常.

这是一个没有Dropwizard东西的最小例子来演示这个问题:

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runner.RunWith;
import org.junit.runners.model.Statement;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class TestTest {
    @Mock String foo;

    @Rule
    public TestRule testRule = new TestRule() {
        {
            assert foo != null; // <<< this assertions fails
        }

        @Override
        public Statement apply(Statement statement, Description description) {
            return statement;
        }
    };

    @Test
    public void test() {

    }
}

如果我可以控制@Mock和@Rule之间的顺序,我可以避免这个问题.或许还有一个我没想到的替代方案.

任何建议表示赞赏,谢谢!

解决方法:

这不是@Rule注释的问题,而是测试类的成员变量的初始化.创建测试实例时,将初始化规则实例(resources或testRule).即使没有附加@Rule注释,也会发生这种情况(这是简单的java逻辑:构造对象实例时,所有成员变量都将在构造期间初始化).

因此,当Mockito创建foo mock时,已经创建了resources或testRule.如果您使用MockitoRule,则此行为不会更改.
@Rule注释只是告诉JUnit使用创建的对象作为规则,它不控制规则的创建.

所以我想唯一的解决方案是确实在测试初始化​​期间创建foo模拟,即使用Foo foo = mock(Foo.class)

上一篇:mysql – Dropwizard Hibernate配置


下一篇:2021年Android程序员职业规划!系列篇