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

Dav*_*vid 8 java junit junit5

我正在用 JUnit 5 编写一些 JUnit 测试。在每次测试之前,我需要加载一个测试资源并用它初始化一些其他东西。为此,我编写了带有 注释的 init 方法@BeforeEach,因为除了要加载的资源对于每个测试应该是不同的资源之外,进度总是相同的。
我首先想到的是去掉@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);
   }

}
Run Code Online (Sandbox Code Playgroud)

这样我觉得我正在破坏 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;
      }

   }
Run Code Online (Sandbox Code Playgroud)

我不喜欢那个解决方案,因为我首先没有安全性让编译器确保正确的名称,其次要加载的资源第一眼看上去没有明显连接到相应的测试。然后我认为以某种方式向注释提供资源路径会很好,该注释直接附加到测试方法。类似的东西:

@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();
     }
Run Code Online (Sandbox Code Playgroud)

不幸的是,@Test注释没有定义任何参数,经过对 JUnit 文档的一些研究,我在这里找不到任何其他的注释。我现在能想到的最好的事情是创建我自己的注释并将其放在每个测试方法上。但我也认为这是一个普遍的问题,不用自己重新发明轮子就可以解决。我只是找不到任何东西。
有没有一种方便的方法来解决这个问题,不需要自己发明注释。换句话说:是否有一种简单的方法可以通过使用已经存在的框架 API 来保持代码质量和可读性来解决这个问题?

Dak*_*rra 6

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());
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 感谢您的评论。这并不完全是我想要的,但发现“@BeforeEach”可以接收“TestInfo”参数很有用。就我而言,“TestInfo.getTags()”是我所需要的(因此我可以通过向某些测试方法添加“@Tag”注释来参数化“@BeforeEach”方法的某些部分)。有用! (2认同)