首页 文章

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

提问于
浏览
0

我正在用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 注释在这里没有找到任何其他注释 . 我现在能想到的最好的事情是创建我自己的注释并将其放在每个测试方法上 . 但我也认为这是一个常见的问题,可以在不重新改造自己的情况下解决 . 我什么都找不到 .
有没有一种方便的方法来解决这个问题,不需要发明自己的注释 . 换句话说:有没有一种简单的方法,通过使用已经存在的框架API来保持代码质量和可读性来解决这个问题?

2 回答

  • 0

    如果您具有相同的测试步骤,但想要使用不同的参数执行它,则 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());
        }
    }
    
  • 2

    我想,你在寻找"container templates" . 它们不是木星的一部分 . 但已经预定为5.4:https://github.com/junit-team/junit5/issues/871

相关问题