JUnit参数化测试
JUnit参数化测试允许我们使用不同的参数多次运行测试方法。
JUnit 5提供了许多将参数传递给测试方法的方法。
JUnit参数化测试
我们需要遵循其他依赖关系才能在测试案例中使用参数化测试。
<dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-params</artifactId> <version>5.2.0</version> <scope>test</scope> </dependency>
我们必须使用带有测试方法的@ParameterizedTest来代替通用的@Test注解。
我们还必须提供一个将为该方法生成参数的源。
我们可以在参数化测试方法中定义和使用多种类型的源。
使用@ValueSource的JUnit参数化测试
这是参数化测试的最简单形式,我们可以使用@ValueSource传递参数数组。
我们可以使用ValueSource批注传递原始数据类型数组,字符串数组或者类数组。
@ParameterizedTest @ValueSource(ints = { 1, 2, 3 }) void test_ValueSource(int i) { System.out.println(i); } @ParameterizedTest @ValueSource(strings = { "1", "2", "3" }) void test_ValueSource_String(String s) { assertTrue(Integer.parseInt(s) < 5); }
JUnit @ParameterizedTest与@EnumSource
@EnumSource允许我们将枚举传递给我们的测试方法。
@ParameterizedTest @EnumSource(ElementType.class) void test_EnumSource(ElementType et) { System.out.println(et); }
如果只需要Enum中的特定值,则可以使用EnumSource name参数来实现。
@ParameterizedTest @EnumSource(value = ElementType.class, names = { "TYPE", "METHOD", "FIELD" }) void test_EnumSource_Extended(ElementType et) { assertTrue(EnumSet.of(ElementType.FIELD, ElementType.TYPE, ElementType.METHOD).contains(et)); }
使用@MethodSource的JUnit @ParameterizedTest
我们可以使用@MethodSource来指定测试参数的工厂方法。
此方法可以存在于同一类或者任何其他类中。
工厂方法应该是静态的,并返回Strem,Iterator,Iterable或者元素数组。
@ParameterizedTest @MethodSource("ms") void test_MethodSource(String s) { assertNotNull(s); } static Stream<String> ms() { return Stream.of("A", "B"); }
我们还可以使用MethodSource将多个参数传递给测试方法。
在这种情况下,我们将不得不使用Arguments
API。
让我们用工厂方法源定义一个单独的类。
package com.theitroad.parameterizedtests; import java.util.stream.Stream; import org.junit.jupiter.params.provider.Arguments; public class MethodSources { public static Stream<Arguments> msMP() { return Stream.of(Arguments.of(1, "A"), Arguments.of(2, "B"), Arguments.of(3, "C")); } }
相应的JUnit参数化测试方法将定义为:
@ParameterizedTest @MethodSource("com.theitroad.parameterizedtests.MethodSources#msMP") void test_MethodSource_MultipleParams(int i, String s) { assertTrue(4 > i); assertTrue(Arrays.asList("A", "B", "C").contains(s)); }
JUnit MethodSource与TestNG DataProvider批注非常相似。
JUnit @ParameterizedTest与@CsvSource
我们还可以将CSV值传递给测试方法。
我们可以在测试方法中为多个参数指定分隔符。
@ParameterizedTest @CsvSource(delimiter='|', value= {"1|'A'","2|B"}) void test_CsvSource(int i, String s) { assertTrue(3 > i); assertTrue(Arrays.asList("A", "B", "C").contains(s)); }
带有CSV文件的JUnit参数化测试
我们可以使用@CsvFileSource批注将CSV数据从文件传递到参数化测试方法。
我们可以跳过标题行并定义我们的自定义定界符。
假设我们将" country_code.csv"文件定义为:
Country,TelephoneCode USA,1 San Franceco,91
这是将CSV文件数据用于参数映射的测试方法。
@ParameterizedTest @CsvFileSource(resources = "/country_code.csv", numLinesToSkip = 1) void test_CsvFileSource(String country, int code) { assertNotNull(country); assertTrue(0 < code); }
带对象的JUnit参数化测试
到目前为止,我们在示例中使用了基元和字符串,但是在现实生活中,大多数时候我们都必须传递对象。
我们可以使用@MethodSource来实现此功能。
假设我们将Book类定义为:
class Book { private String title; //standard getter setters public Book(String t) { this.title = t; } @Override public String toString() { return title; } }
现在,我们可以使用以下工厂方法将Book对象传递给我们的测试方法。
static Book[] mpBooks() { return new Book[] {new Book("Harry Potter"), new Book("Five Point Someone")}; } @ParameterizedTest @MethodSource("mpBooks") void test_MethodSource_Objects(Book b) { assertNotNull(b.getTitle()); }
请注意,这一次我返回的是Book数组,而之前我返回的是元素流。
JUnit参数化测试参数验证
如果要通过Eclipse运行测试用例,则可以检查方法参数以确保将正确的值传递给参数化测试。
JUnit测试方法参数转换
JUnit为许多类型转换器提供内置支持。
其中一些是int到long,字符串是boolean,反之亦然,字符串是enum,是日期时间对象。
下面的代码也将起作用,并且JUnit将自动调用我们的Book类构造函数以将String值转换为Book对象。
@ParameterizedTest @ValueSource(strings = {"Harry Potter", "Hamlet"}) void test_ValueSource_Objects(Book b) { assertNotNull(b.getTitle()); }
但是,如果更改Book类的构造函数,则在执行测试用例时可能会导致错误。
最好使用MethodSource并提供我们自己的对象创建机制。