Java编写Wordle类程序JUnit测试:多参数方法优化方案咨询
解决JUnit测试重复代码的最佳实践
针对你遇到的测试代码重复、参数过多的问题,完全没必要保留重复代码或者用10+参数的方法,以下几种优雅方案可以解决:
1. 用值对象封装测试预期参数
创建一个专门的类来封装所有测试Letter需要的预期值,把分散的参数打包成一个对象,再封装统一的断言方法。
步骤示例:
首先定义预期值类:
class LetterExpectation { private final char expectedChar; private final int expectedMinOcc; private final int expectedMaxOcc; private final Set<Integer> expectedCorrectPositions; private final Set<Integer> expectedIncorrectPositions; // 构造器 public LetterExpectation(char expectedChar, int expectedMinOcc, int expectedMaxOcc, Set<Integer> expectedCorrectPositions, Set<Integer> expectedIncorrectPositions) { this.expectedChar = expectedChar; this.expectedMinOcc = expectedMinOcc; this.expectedMaxOcc = expectedMaxOcc; this.expectedCorrectPositions = expectedCorrectPositions; this.expectedIncorrectPositions = expectedIncorrectPositions; } // Getters public char getExpectedChar() { return expectedChar; } public int getExpectedMinOcc() { return expectedMinOcc; } public int getExpectedMaxOcc() { return expectedMaxOcc; } public Set<Integer> getExpectedCorrectPositions() { return expectedCorrectPositions; } public Set<Integer> getExpectedIncorrectPositions() { return expectedIncorrectPositions; } }
然后封装断言逻辑:
private void assertLetterMatches(Letter actualLetter, LetterExpectation expectation) { // 验证基础属性 assertEquals(expectation.getExpectedChar(), actualLetter.getLett()); assertEquals(expectation.getExpectedMinOcc(), actualLetter.getMinOcc()); assertEquals(expectation.getExpectedMaxOcc(), actualLetter.getMaxOcc()); Set<Integer> actualCorrect = actualLetter.getCorrect(); Set<Integer> actualIncorrect = actualLetter.getIncorrect(); // 验证所有位置的正确/错误状态 for (int pos = 0; pos < 5; pos++) { assertEquals(expectation.getExpectedCorrectPositions().contains(pos), actualCorrect.contains(pos)); assertEquals(expectation.getExpectedIncorrectPositions().contains(pos), actualIncorrect.contains(pos)); } }
测试用例中调用:
LetterExpectation aExpectation = new LetterExpectation('A', 0, 0, Collections.emptySet(), Collections.emptySet()); assertLetterMatches(g1.getLetter('A'), aExpectation);
2. 结合JUnit参数化测试批量处理场景
如果有多个Letter的测试场景,用JUnit 5的参数化测试可以进一步减少重复,把所有测试数据集中管理:
@ParameterizedTest @MethodSource("letterTestData") void testLetterProperties(Letter actualLetter, LetterExpectation expectation) { assertLetterMatches(actualLetter, expectation); } private static Stream<Arguments> letterTestData() { return Stream.of( Arguments.of(g1.getLetter('A'), new LetterExpectation('A', 0, 0, Collections.emptySet(), Collections.emptySet())), Arguments.of(g1.getLetter('B'), new LetterExpectation('B', 1, 1, Set.of(2), Collections.emptySet())), // 添加更多测试场景 Arguments.of(g1.getLetter('C'), new LetterExpectation('C', 0, 1, Collections.emptySet(), Set.of(0, 3))) ); }
3. 用自定义断言库简化代码
如果项目中使用AssertJ(推荐的Java断言库),可以编写自定义断言类,让测试代码更具可读性和流畅性:
class LetterAssert extends AbstractAssert<LetterAssert, Letter> { public LetterAssert(Letter actual) { super(actual, LetterAssert.class); } public static LetterAssert assertThat(Letter actual) { return new LetterAssert(actual); } public LetterAssert hasChar(char expectedChar) { isNotNull(); assertEquals(expectedChar, actual.getLett(), "Letter should be %c", expectedChar); return this; } public LetterAssert hasMinOccurrence(int expectedMin) { isNotNull(); assertEquals(expectedMin, actual.getMinOcc(), "Min occurrence should be %d", expectedMin); return this; } public LetterAssert hasMaxOccurrence(int expectedMax) { isNotNull(); assertEquals(expectedMax, actual.getMaxOcc(), "Max occurrence should be %d", expectedMax); return this; } public LetterAssert hasNoCorrectPositions() { isNotNull(); for (int pos = 0; pos < 5; pos++) { assertFalse(actual.getCorrect().contains(pos), "Should have no correct positions, but found %d", pos); } return this; } public LetterAssert hasNoIncorrectPositions() { isNotNull(); for (int pos = 0; pos < 5; pos++) { assertFalse(actual.getIncorrect().contains(pos), "Should have no incorrect positions, but found %d", pos); } return this; } }
测试用例中直接链式调用:
assertThat(g1.getLetter('A')) .hasChar('A') .hasMinOccurrence(0) .hasMaxOccurrence(0) .hasNoCorrectPositions() .hasNoIncorrectPositions();
内容的提问来源于stack exchange,提问作者Lee Buhrmann
相关产品推荐
相关产品推荐

