JUnit5 ParameterizedTest:如何用CsvSource实现多断言逻辑复用测试
解决单个参数化测试中动态切换断言逻辑的问题
这个痛点我太懂了——重复写几乎一样的测试方法简直是代码洁癖的噩梦!其实只需要给你的参数化数据源加一个断言类型标记,就能在单个测试方法里灵活切换assertEquals和assertNotEquals,完全避免代码重复。
方法一:用布尔值作为断言标记
最简单的方式就是在@CsvSource里新增一个布尔参数,用来标识当前用例应该使用相等断言还是不等断言:
import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; import static org.junit.jupiter.api.Assertions.*; @ParameterizedTest @CsvSource({ "apple, apple, true", // 预期相等,用assertEquals "apple, banana, false", // 预期不等,用assertNotEquals "123, 123, true", "456, 789, false" }) void testDynamicEqualityChecks(Object actual, Object expected, boolean shouldBeEqual) { if (shouldBeEqual) { assertEquals(expected, actual); } else { assertNotEquals(expected, actual); } }
方法二:用枚举提升可读性
如果觉得布尔值不够直观(比如过段时间忘了true代表啥),可以自定义一个枚举类来明确断言类型,代码可读性会更好:
import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; import static org.junit.jupiter.api.Assertions.*; // 定义断言类型枚举 enum AssertAction { ASSERT_EQUAL, ASSERT_NOT_EQUAL } @ParameterizedTest @CsvSource({ "cat, cat, ASSERT_EQUAL", "dog, cat, ASSERT_NOT_EQUAL", "'hello world', 'hello world', ASSERT_EQUAL" }) void testWithEnumMarkers(String actual, String expected, AssertAction action) { switch (action) { case ASSERT_EQUAL -> assertEquals(expected, actual); case ASSERT_NOT_EQUAL -> assertNotEquals(expected, actual); } }
额外小技巧
如果你的断言逻辑以后可能扩展(比如要加assertTrue/assertFalse之类的),还可以把断言逻辑封装成独立的方法,然后根据标记调用对应的方法,这样测试方法会更简洁,也方便后续维护。
内容的提问来源于stack exchange,提问作者Zon
相关产品推荐
相关产品推荐

