【发布时间】:2020-09-03 22:09:16
【问题描述】:
我的任务是计算给定两个字符串中不匹配(不同字符)的数量。虽然;有两个条件需要满足。
如果给定的两个字符串的长度不同; 抛出带有适当消息的异常。
如果只提供一个输入字符串; 抛出带有适当消息的异常。
我的解决方案:
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;
}
}
现在,当我直接运行此解决方案时;它按预期工作。可以找到上面代码的运行样例here.
当我尝试使用 Junit 测试覆盖率 运行相同的代码时;相同的代码使所有涉及异常的测试用例失败。下面是我的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 项目。因此生成的报告显示以下问题:
什么解决了我的问题:
长时间工作后;当我最终尝试将异常抛出条件放入构造函数中时;它解决了我的问题。每个测试用例都通过了。比如:
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;
}
我有什么疑问:
- 为什么将异常抛出条件放在构造函数中的解决方案有效?
- 当我试图将异常抛出条件放在
getHamming()方法中时;为什么测试失败了? - 当我在没有 JUnit 的情况下运行前面提到的
Hamming类时;它按预期工作。为什么会这样?
任何帮助都会有所帮助。
【问题讨论】:
-
在你失败的测试中,你不调用抛出异常的方法,你只调用构造函数。
-
顺便说一句,不需要创建 Hamming 类的实例:只需将方法声明为静态,并将两个字符串作为参数。
-
@AndyTurner;谢谢你。我是多么痛苦,我错过了它。我只有一个疑问;将异常条件放在构造函数中是否是最佳实践,或者我们可以做其他事情如果我们不允许编辑 TestHamming.java 类。
-
最好的做法是尽快失败,以使失败尽可能接近导致它的原因(传递空/不相等的字符串)。特别是,这里没有在构造函数中放置异常会给您留下一个完全瘫痪的
Hamming实例,它总是会抛出异常。如果你在构造函数中抛出异常,你永远不会得到这个无效的实例。
标签: java unit-testing gradle exception junit4