如何让JUnit测试依次使用不同初始化逻辑重复执行?
嘿,这个需求太常见了——想让同一套测试逻辑跑在不同的Set实现上,又不想在测试方法里手动改初始化代码,更不想复制粘贴重复测试对吧?刚好JUnit有现成的机制能搞定,给你几个实用的方案,适配不同的JUnit版本:
方案1:JUnit4 参数化测试(推荐,最优雅)
这种方式让测试框架自动为每个Set实现生成测试实例,跑完全部测试方法,完全不用重复代码。
你只需要给测试类加上@RunWith(Parameterized.class)注解,定义参数接收不同的Set实现,再提供数据源即可:
import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import java.util.Set; import java.util.HashSet; import java.util.TreeSet; import java.util.Arrays; import java.util.Collection; @RunWith(Parameterized.class) public class SomeTest { private Set<Integer> set; // 构造方法接收Set实现实例 public SomeTest(Set<Integer> set) { this.set = set; } // 提供测试用的Set实现集合 @Parameterized.Parameters(name = "使用{0}测试") public static Collection<Object[]> data() { return Arrays.asList(new Object[][] { { new HashSet<Integer>() }, { new TreeSet<Integer>() } }); } // 你的测试方法完全不用改,直接用set变量 @Test public void testAddElement() { set.add(1); assert set.contains(1); } @Test public void testDuplicateAdd() { set.add(2); set.add(2); assert set.size() == 1; } }
运行后,框架会自动用HashSet和TreeSet各跑一遍所有测试,测试报告还会标注每个测试用的是哪种实现,排查问题超方便。
方案2:继承式拆分(适合不想大幅修改原有测试的场景)
如果你已经写了大量测试方法,不想改原有类的结构,可以把测试逻辑抽成父类,再写两个子类分别初始化不同的Set:
首先是父类(存放所有测试逻辑,去掉原有的@Before):
import org.junit.Test; import java.util.Set; public abstract class BaseSetTest { protected Set<Integer> set; // 所有测试方法都放这里,不用做任何修改 @Test public void testAddElement() { set.add(1); assert set.contains(1); } @Test public void testDuplicateAdd() { set.add(2); set.add(2); assert set.size() == 1; } }
然后是HashSet的测试子类:
import org.junit.Before; import java.util.HashSet; public class HashSetTest extends BaseSetTest { @Before public void init() { set = new HashSet<>(); } }
再写TreeSet的测试子类:
import org.junit.Before; import java.util.TreeSet; public class TreeSetTest extends BaseSetTest { @Before public void init2() { set = new TreeSet<>(); } }
运行这两个子类,就会分别用不同的Set实现执行所有测试,原有测试逻辑完全保留。
补充:如果你用的是JUnit5(Jupiter)
JUnit5的参数化测试更灵活简洁,直接用@ParameterizedTest配合@MethodSource即可:
import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import java.util.Set; import java.util.HashSet; import java.util.TreeSet; import java.util.stream.Stream; public class SomeTest { // 提供Set实现的数据源 static Stream<Set<Integer>> setImplementations() { return Stream.of(new HashSet<>(), new TreeSet<>()); } // 每个Set实现跑一遍测试 @ParameterizedTest @MethodSource("setImplementations") public void testAddElement(Set<Integer> set) { set.add(1); assert set.contains(1); } @ParameterizedTest @MethodSource("setImplementations") public void testDuplicateAdd(Set<Integer> set) { set.add(2); set.add(2); assert set.size() == 1; } }
内容的提问来源于stack exchange,提问作者serhii
相关产品推荐
相关产品推荐

