【问题标题】:Initialize a List<?> in a JUnit via @Rule通过 @Rule 在 JUnit 中初始化 List<?>
【发布时间】:2018-07-17 20:27:43
【问题描述】:

我正在编写一个 JUnit 测试用例。我想初始化一个列表对象。为简洁起见,让我们初始化一个 String 对象列表:

public class MyTest {
    @Rule
    public List<MySQLContainer> tests = Arrays.asList(new MySQLContainer("5.5"), new MySQLContainer("5.6"));

    @Test
    public void myTest() {

    }
}

执行时出现以下运行时错误:

org.junit.internal.runners.rules.ValidationError: The @Rule 'tests' must implement MethodRule or TestRule.
at org.junit.internal.runners.rules.RuleMemberValidator$FieldMustBeARule.validate(RuleMemberValidator.java:234)
at org.junit.internal.runners.rules.RuleMemberValidator.validateMember(RuleMemberValidator.java:99)
at org.junit.internal.runners.rules.RuleMemberValidator.validate(RuleMemberValidator.java:93)
at org.junit.runners.BlockJUnit4ClassRunner.validateFields(BlockJUnit4ClassRunner.java:196)
at org.junit.runners.BlockJUnit4ClassRunner.collectInitializationErrors(BlockJUnit4ClassRunner.java:1

当我简单地初始化 MySQLContainer 而不是 List&lt;MySQLContainer&gt; 时,我没有收到此类错误。

为什么这不起作用?我该如何解决?

我的依赖项中有 JUnit 4.12。

【问题讨论】:

  • 你为什么还需要@Rule 注释呢?你到底想达到什么目的?
  • 在我的情况下,我正在初始化来自 TestContainers 项目的 MySQLContainer 实例。我会编辑我的帖子。
  • 这看起来仍然像一个常量列表。为什么你需要@Rule
  • 我想要@Rule 背后的功能。我希望 MySQL 容器在每次测试之前初始化。我知道这是@Rule的目标?

标签: java junit junit4 junit-rule


【解决方案1】:

尝试使用 ArrayList()

    public List<MySQLContainer> tests = new ArrayList();

【讨论】:

    【解决方案2】:

    @Rules 用于在每个测试方法之前执行代码。如果只需要初始化一个成员,把这个初始化放在一个用@Before注解的方法中:

    public class MyTest {    
        private List<MySQLContainer> containers;
    
        @Before
        public void initContainers() {
            containers =  = Arrays.asList(new MySQLContainer("5.5"), new MySQLContainer("5.6"));
        }
    
        @Test
        public void myTest() {
            // Some test...    
        }
    }
    

    【讨论】:

    • 使用@Before 是个好主意。我现在使用@Before 并在每个容器上调用.start()
    • @After 在每个容器上调用.stop()
    • 您不必使用@Before。只需删除@Rule,一切都很好。
    • @StefanBirkner 没有关于何时实例化测试类的约定。如果您在测试类的构造函数中初始化一个成员(或内联,这隐含地意味着它在每个构造函数中都被初始化),您可能会在测试之间获得相同的实例。有时这是可以的(例如,如果它是静态/常量数据),但有时测试 X 可能会修改此数据并在测试 Y 中产生意外行为。OP 没有提供足够的上下文来辨别是否是这种情况,但通常说这是一种不好的做法,除非您有非常充分的理由这样做,否则应该避免这样做。
    • 默认 JUnit 运行器有一个隐式契约。它为每个测试创建一个新的测试类实例。因此你不需要@Before。其他运行器可能会重用测试实例,但这种情况非常少见。另见martinfowler.com/bliki/JunitNewInstance.html
    【解决方案3】:

    删除@Rule,一切正常。

    public class MyTest {
    
        private final List<MySQLContainer> tests = Arrays.asList(
            new MySQLContainer("5.5"),
            new MySQLContainer("5.6")
        );
    
        @Test
        public void myTest() {
    
        }
    }
    

    @Rule 用于 JUnit 4 扩展,可以做一些更复杂的事情。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-08-04
      • 1970-01-01
      • 2016-09-13
      • 1970-01-01
      • 1970-01-01
      • 2018-02-10
      • 2016-06-14
      • 2015-04-08
      相关资源
      最近更新 更多