首页 > 解决方案 > 管理检查 JUnit 中抛出的 ExpectedException 的规则

问题描述

我的任务是计算给定两个字符串中不匹配(不同字符)的数量。虽然; 有两个条件需要满足。

如果给定的两个字符串的长度不同;抛出带有适当消息的异常。

如果只提供一个输入字符串;抛出带有适当消息的异常。

我的解决方案:

class Hamming {
    private final String leftString;
    private final String rightString;

    public Hamming(String leftString, String rightString) {
        this.leftString = leftString;
        this.rightString = rightString;
    }

    public int getHammingDistance() {
        int hammingDistance = 0;
        int secondCharIndex = 0;
        if (leftString.length() == 0 && rightString.length() != 0)
            throw new IllegalArgumentException("left string must not be empty.");
        if (rightString.length() == 0 && leftString.length() != 0)
            throw new IllegalArgumentException("right string must not be empty.");
        if (leftString.length() != rightString.length())
            throw new IllegalArgumentException("left and right string must be of equal length.");
        for (char ch : leftString.toCharArray()) {
            if (ch != rightString.charAt(secondCharIndex)) hammingDistance++;
            secondCharIndex++;
        }
        return hammingDistance;
    }
}


现在,当我直接运行此解决方案时;它按预期工作。您可以在此处找到上述代码的运行示例

当我尝试使用Junit Test Coverage运行相同的代码时;相同的代码使所有涉及异常的测试用例失败。下面是我的HammingTest.java

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThrows;

import org.junit.Ignore;
import org.junit.Test;

public class HammingTest {

    @Test
    public void testNoDistanceBetweenEmptyStrings() {
        assertEquals(0, new Hamming("", "").getHammingDistance());
    }

//    @Ignore("Remove to run test")
    @Test
    public void testNoDistanceBetweenShortIdenticalStrings() {
        assertEquals(0, new Hamming("A", "A").getHammingDistance());
    }

//    @Ignore("Remove to run test")
    @Test
    public void testCompleteDistanceInSingleLetterDifferentStrings() {
        assertEquals(1, new Hamming("G", "T").getHammingDistance());
    }

//    @Ignore("Remove to run test")
    @Test
    public void testDistanceInLongIdenticalStrings() {
        assertEquals(0, new Hamming("GGACTGAAATCTG", "GGACTGAAATCTG").getHammingDistance());
    }

//    @Ignore("Remove to run test")
    @Test
    public void testDistanceInLongDifferentStrings() {
        assertEquals(9, new Hamming("GGACGGATTCTG", "AGGACGGATTCT").getHammingDistance());
    }

//    @Ignore("Remove to run test")
    @Test
    public void testValidatesFirstStringNotLonger() {
        IllegalArgumentException expected =
            assertThrows(
                IllegalArgumentException.class,
                () -> new Hamming("AATG", "AAA"));

        assertThat(expected)
            .hasMessage("left and right string must be of equal length.");
    }

//    @Ignore("Remove to run test")
    @Test
    public void testValidatesSecondStringNotLonger() {
        IllegalArgumentException expected =
            assertThrows(
                IllegalArgumentException.class,
                () -> new Hamming("ATA", "AGTG"));

        assertThat(expected)
            .hasMessage("left and right string must be of equal length.");
    }

//    @Ignore("Remove to run test")
    @Test
    public void testDisallowLeftEmptyString() {
        IllegalArgumentException expected =
            assertThrows(
                IllegalArgumentException.class,
                () -> new Hamming("", "G"));

        assertThat(expected)
            .hasMessage("left string must not be empty.");
    }

//    @Ignore("Remove to run test")
    @Test
    public void testDisallowRightEmptyString() {
        IllegalArgumentException expected =
            assertThrows(
                IllegalArgumentException.class,
                () -> new Hamming("G", ""));

        assertThat(expected)
            .hasMessage("right string must not be empty.");
    }

}

我将该项目用作gradle 项目。因此生成的报告显示了以下问题:

在此处输入图像描述

什么解决了我的问题:

长期工作后;当我最终尝试将异常抛出条件放入 Constructor 时;它解决了我的问题。每个测试用例都通过了。就像是:

public Hamming(String leftString, String rightString) {
        if (leftString.length() == 0 && rightString.length() != 0) {
            throw new IllegalArgumentException("left string must not be empty.");
        } else if (rightString.length() == 0 && leftString.length() != 0) {
            throw new IllegalArgumentException("right string must not be empty.");
        } else if (leftString.length() != rightString.length()) {
            throw new IllegalArgumentException("leftString and rightString must be of equal length.");
        }
        this.leftSting = leftString;
        this.rightString = rightString;
    }

我有什么疑问:

  1. 为什么将异常抛出条件放在构造函数中的解决方案有效?
  2. 当我试图将异常抛出条件放入getHamming()方法中时;为什么测试失败了?
  3. 当我在Hamming没有 JUnit 的情况下运行与前面提到的相同的类时;它按预期工作。为什么会这样?

任何帮助都会有所帮助。

标签: javaunit-testinggradleexceptionjunit4

解决方案


您错过了电话getHammingDistance(),这就是您的测试用例失败的原因。让我们举一个测试用例,看看为什么。

@Test
public void testValidatesFirstStringNotLonger() {
    IllegalArgumentException expected =
        assertThrows(
            IllegalArgumentException.class,
            () -> new Hamming("AATG", "AAA"));

    assertThat(expected)
        .hasMessage("left and right string must be of equal length.");
}

第一个assertThrows检查是否new Hamming("AATG", "AAA")失败并带有IllegalArgumentException. 由于异常是在方法中引发的getHammingDistance(),因此断言失败。

这会奏效:

@Test
public void testValidatesFirstStringNotLonger() {
    Hamming hamming = new Hamming("AATG", "AAA");

    IllegalArgumentException expected =
        assertThrows(
            IllegalArgumentException.class,
            () -> hamming.getHammingDistance());

    assertThat(expected)
        .hasMessage("left and right string must be of equal length.");
}

推荐阅读