java 类级的JUnit5参数化测试

iaqfqrcu  于 2023-04-28  发布在  Java
关注(0)|答案(3)|浏览(169)

是否有可能使用JUnit5的参数化新特性来运行测试类来接收测试参数,而不是在方法级执行?
对于JUnit 4,可以使用@RunWith(Parameterized::class)这样的运行器加上继承来将参数数组传递给子类,但我不确定是否可以使用新的JUnit 5 API来实现等效的功能。

suzh9iv8

suzh9iv81#

简短的回答
无法使用JUnit 5按照JUnit 4的样式参数化 * 类创建 *。
幸运的是,分离测试逻辑和测试输入数据(参数)的意图可以以不同的方式实现。

JUnit 5有自己的参数化测试方法,当然与JUnit 4不同。新方法不允许在类级别使用参数化的fixture,即即通过其每一种测试方法。因此,每个参数化的测试方法都应该显式地使用 link to parameters 进行注解。
JUnit 5提供了大量的参数源类型,可以在文档和guides中找到

在您的示例中,从Junit 4@Parameters迁移的最简单方法是使用@MethodSourceorg.junit.jupiter.params.provider.*@ArgumentsSource
[***] JUnit 4**:

@RunWith(Parameterized.class)
public class MyTestWithJunit4 {
    @Parameters
    public static Collection<Object[]> data() {
      return Arrays.asList(new Object[][] {     
               { 0, 0, 0 },
               { 1, 2, 3 }, 
               { 5, 3, 8 } 
      });
    }

    int first;
    int second;
    int sum;

    public MyTestWithJunit4(int first, int second, int sum) {
      this.first = first;
      this.second = second;
      this.sum = sum;
    }

    @Test
    public void test() {
      assertEquals(sum, first + second));
    }
}

JUnit 5(带@MethodSource

class MyTestWithJunit5 {

  @DisplayName("Test with @MethodSource")
  @ParameterizedTest(name = "{index}: ({0} + {1}) => {2})")
  @MethodSource("localParameters")
  void test(int first, int second, int sum) {
    assertEquals(sum, first + second);
  }

  static Stream<Arguments> localParameters() {
    return Stream.of(
        Arguments.of(0, 0, 0),
        Arguments.of(1, 2, 3),
        Arguments.of(5, 3, 8)
    );
  }
}

JUnit 5(带@ArgumentsSource

class MyTestWithJunit5 {
  @DisplayName("Test with @ArgumentsSource")
  @ParameterizedTest(name = "{index}: ({0} + {1}) => {2})")
  @ArgumentsSource(Params.class)
  void test(int first, int second, int sum) {
    assertEquals(sum, first + second);
  }

  static class Params implements ArgumentsProvider {
    @Override
    public Stream<? extends Arguments> provideArguments(ExtensionContext context) {
      return Stream.of(
          Arguments.of(0, 0, 0),
          Arguments.of(1, 2, 3),
          Arguments.of(5, 3, 8)
      );
    }
  }
}

考虑到@MethodSource中的方法和@ArgumentsSource中的类可以在任何地方描述,而不仅仅是在测试方法所在的同一个类中。此外,@MethodSource允许提供多个源方法,因为它的valueString[]

一些备注和比较

JUnit 4中,我们只能有一个提供参数的工厂方法,并且测试应该围绕这些参数构建。相反,JUnit 5在绑定参数方面提供了更多的抽象性和灵活性,并将测试逻辑与其参数解耦,这是次要的。这允许独立于参数源构建测试,并在需要时轻松更改它们。

依赖需求

参数化测试功能不包括在核心junit-jupiter-engine中,但位于单独的依赖项junit-jupiter-params中。

vnjpjtjt

vnjpjtjt2#

创建指定参数化的 meta注解,并将其应用于测试方法:

public class MyTest {
    @ParameterizedTest(name = "{0}")
    @MethodSource("allImplementations")
    @Retention(RetentionPolicy.RUNTIME)
    private @interface TestAllImplementations {
    }

    static Stream<Arguments> allImplementations() {
        return Stream.of(
             Arguments.of("Serial", new SerialWidget()),
             Arguments.of("Concurrent", new ConcurrentWidget())
        );
    }

    @TestAllImplementations
    void myFirstTest(String name, Widget implementation) {
        /* ... */
    }

    @TestAllImplementations
    void mySecondTest(String name, Widget implementation) {
        /* ... */
    }
}
zkure5ic

zkure5ic3#

@ParameterizedTest()
@MethodSource("dataProvider")
void testWithDataProvider(String str, List<JSONObject> list) {
    System.out.println();

}

static Stream<Arguments> dataProvider() {
    String json = """
            {
                "test":1 
            }
                    """;
    return Stream.of(
            arguments("abc", Arrays.asList(new JSONObject(json))),
            arguments("lemon", Arrays.asList(new JSONObject(json)))
    );

我用这种方式绕过了这种复杂性

相关问题