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

问题描述 投票:4回答:1

我有一个测试类,它正在测试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初始化模拟之前运行,因此当foo被实例化时BarResource为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之间的顺序,我可以避免这个问题。或许还有一个我没想到的替代方案。

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

java junit mockito dropwizard
1个回答
2
投票

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

因此,当Mockito创建foo模拟时,resourcestestRule已经创建。如果您使用MockitoRule,则此行为不会更改。而@Rule注释只是告诉JUnit使用创建的对象作为规则,它不控制规则的创建。

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

© www.soinside.com 2019 - 2024. All rights reserved.