运行 具有从同一接口派生的多个对象的同一 Junit 测试
Run same Junit Test with multiple objects derived from same interface
我正在努力提高我的测试知识 我正在尝试 运行使用从同一接口派生的不同对象实现相同的 JUnit 测试 class。
所以我们可以假设如下:
interface Base {
void sort();
}
class A implements Base {
@Override
public void sort() {
//sort naively
}
}
class B implements Base {
@Override
public void sort() {
//sort using another better approach
}
}
class C implements Base {
@Override
public void sort() {
//sort using optimized approach
}
}
class Test {
@Test
void test1() {
Base obj = new A();
obj.sort();
obj.otherStuff();
}
}
class SecondTest {
//trying to avoid making multiple test classes that has only one line in difference
@Test
void test1() {
var obj = new B();
obj.sort();
obj.otherStuff();
}
所以我的问题是如何 运行 使用 A、B、C 中的对象进行测试 class 而不会落入重复代码和冗余的陷阱?
请注意,我写这个例子只是为了说明我的观点,sort()
doStuff()
方法只是占位符,但是当你在每个测试中有超过 ~70 行代码重复时 class 它开始变得丑陋和多余。
*我看过@beforeEach、@Before、@After,但我认为我看不到这些可能对我有帮助的方法。
修复它的方法如下,您在测试 class 中创建一个方法,该方法将 Base obj
作为输入并包含所有重复行。然后你要做的是在不同的测试中初始化 obj
,然后将它传递给方法。
这是一个可以完成这项工作的代码:
class Test {
@Test
void test1() {
Base obj = new A();
wrapperMethod(obj);
}
@Test
void test2() {
var obj = new B();
wrapperMethod(obj);
}
public static void wrapperMethod(Base obj){
obj.sort();
obj.otherStuff();
}
}
根据经验,测试可以很像普通编程,其中通过保证可重用性的方法避免冗余。
干杯,
D
你可以写一个parameterized test with a MethodSource.
@ParameterizedTest
@MethodSource("bases")
@Test
void test1(Base obj) {
obj.sort();
obj.otherStuff();
}
static Stream<String> bases() {
return Stream.of(new A(), new B(), new C());
}
首先,您必须确定您对 UnitTesting 的理解。
单元测试与代码(覆盖率)无关。
UnitTesing 是关于验证 期望的 public 行为 其中“public 行为意味着 return 值 and/or 与依赖项的通信。
每个测试方法都应验证测试单元所需行为的单个原子假设。
从这个角度来看,通过相同的测试方法传递一组共享相同接口的对象是没有意义的,因为存在这些不同的接口实现来实现接口方法,它们具有自己的独特性 行为。反过来假设对象的行为方式是唯一不同的。
如果预期所有对象的行为相同(这是单个测试方法可以验证的唯一假设),那么首先没有不同的对象(即实现)。
我正在努力提高我的测试知识 我正在尝试 运行使用从同一接口派生的不同对象实现相同的 JUnit 测试 class。
所以我们可以假设如下:
interface Base {
void sort();
}
class A implements Base {
@Override
public void sort() {
//sort naively
}
}
class B implements Base {
@Override
public void sort() {
//sort using another better approach
}
}
class C implements Base {
@Override
public void sort() {
//sort using optimized approach
}
}
class Test {
@Test
void test1() {
Base obj = new A();
obj.sort();
obj.otherStuff();
}
}
class SecondTest {
//trying to avoid making multiple test classes that has only one line in difference
@Test
void test1() {
var obj = new B();
obj.sort();
obj.otherStuff();
}
所以我的问题是如何 运行 使用 A、B、C 中的对象进行测试 class 而不会落入重复代码和冗余的陷阱?
请注意,我写这个例子只是为了说明我的观点,sort()
doStuff()
方法只是占位符,但是当你在每个测试中有超过 ~70 行代码重复时 class 它开始变得丑陋和多余。
*我看过@beforeEach、@Before、@After,但我认为我看不到这些可能对我有帮助的方法。
修复它的方法如下,您在测试 class 中创建一个方法,该方法将 Base obj
作为输入并包含所有重复行。然后你要做的是在不同的测试中初始化 obj
,然后将它传递给方法。
这是一个可以完成这项工作的代码:
class Test {
@Test
void test1() {
Base obj = new A();
wrapperMethod(obj);
}
@Test
void test2() {
var obj = new B();
wrapperMethod(obj);
}
public static void wrapperMethod(Base obj){
obj.sort();
obj.otherStuff();
}
}
根据经验,测试可以很像普通编程,其中通过保证可重用性的方法避免冗余。
干杯,
D
你可以写一个parameterized test with a MethodSource.
@ParameterizedTest
@MethodSource("bases")
@Test
void test1(Base obj) {
obj.sort();
obj.otherStuff();
}
static Stream<String> bases() {
return Stream.of(new A(), new B(), new C());
}
首先,您必须确定您对 UnitTesting 的理解。
单元测试与代码(覆盖率)无关。
UnitTesing 是关于验证 期望的 public 行为 其中“public 行为意味着 return 值 and/or 与依赖项的通信。 每个测试方法都应验证测试单元所需行为的单个原子假设。
从这个角度来看,通过相同的测试方法传递一组共享相同接口的对象是没有意义的,因为存在这些不同的接口实现来实现接口方法,它们具有自己的独特性 行为。反过来假设对象的行为方式是唯一不同的。
如果预期所有对象的行为相同(这是单个测试方法可以验证的唯一假设),那么首先没有不同的对象(即实现)。