如何在每个@Test的@BeforeEach方法中提供参数

时间:2018-08-28 11:10:15

标签: java junit junit5

我正在用JUnit 5编写一些JUnit测试。在每个测试之前,我需要加载一个测试资源并使用它初始化一些其他内容。为此,我写了一个用@BeforeEach注释的init方法,因为除了每个测试要加载的资源应该是不同的以外,进度总是相同的。
我首先想到的是删除@BeforeEach批注,在init方法中添加一个参数以指定应加载的资源,并在开始时从每次测试中亲自调用init方法。

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.Test;

public class MyTest {
   private Object testResource;

   private void init(String resourcePath) {
      // actually load the resource and initialize some fields here
      this.testResource = "Loaded resource from: " + resourcePath;
   }

   @Test
   public void test0() {
      init("TestResource0");
      assertEquals("Loaded resource from: TestResource0", testResource);
   }

   @Test
   public void test1() {
      init("TestResource1");
      assertEquals("Loaded resource from: TestResource1", testResource);
   }

}

那样,我感觉自己正在破坏JUnit测试流程的整个结构,我担心,这可能会在将来扩展测试时(例如通过以下方式引起)某些问题。一些花哨的元测试编程,我将依靠JUnit提供有关测试当前状态的正确信息。
因此,我决定将要加载的资源参数保留在init方法上,并保留@BeforeEach批注。这样,我需要包含一个ParameterResolver。我对resolveParameter(ParameterContext, ExtensionContext)的实现的第一个想法是首先找出要执行的测试,然后返回要为该测试加载的相应资源。

static class MyParamResolver implements ParameterResolver {

      @Override
      public Object resolveParameter(ParameterContext parameterContext,
                                     ExtensionContext extensionContext) throws ParameterResolutionException {

         String test = extensionContext.getRequiredTestMethod()
                                       .getName();

         switch (test) {
         case "test0":
            return "TestResource0";
         case "test1":
            return "TestResource1";
         }

         throw new ParameterResolutionException("Unknown test " + test);
      }

      @Override
      public boolean supportsParameter(ParameterContext parameterContext,
                                       ExtensionContext extensionContext) {
         return true;
      }

   }

我不喜欢这种解决方案,因为我首先没有安全性来确保编译器确保正确的名称,其次,乍一看显然没有将要加载的资源连接到相应的测试。然后,我认为最好以某种方式将资源路径提供给注释,该注释直接附加到测试方法。像这样:

@Test("test0")
public void test0() {
    assertEquals("Loaded resource from: TestResource0", testResource);
}

@Test("test1")
public void test1() {
   assertEquals("Loaded resource from: TestResource1", testResource);
}

...

    @Override
    public Object resolveParameter(ParameterContext parameterContext,
                                   ExtensionContext extensionContext) {

        return extensionContext.getRequiredTestMethod()
                               .getAnnotation(Test.class)
                               .value();
     }

不幸的是,@Test批注未定义任何参数,并且在JUnit文档中进行了一些研究之后,我在这里找不到任何其他合适的批注。我现在能想到的最好的事情是创建自己的注释并将其放在每种测试方法上。但是我也认为这是一个普遍的问题,无需重新发明自己就可以解决。我什么都找不到。
是否有解决此问题的简便方法,而无需发明自己的注释。换句话说:是否有一种简单的方法,仅使用已经存在的框架API来保持代码质量和可读性来解决此问题?

2 个答案:

答案 0 :(得分:3)

ParameterizedTest在测试步骤相同但又想用不同的参数执行时很有用。事实并非如此。您只需在TestInfo方法中使用@BeforeEach参数即可处理情况。

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInfo;

public class JUnitTest {

    @Test public void test1() {
        System.out.println("Test");
    }

    @BeforeEach public void f(TestInfo info) {
        System.out.println(info.getDisplayName());
    }
}

答案 1 :(得分:1)

我想,您正在寻找“容器模板”。他们还不是木星的一部分。但已计划5.4:https://github.com/junit-team/junit5/issues/871