在 JUnit 中,什么时候应该使用 assertEquals() 什么时候应该使用 try...catch 来验证结果?
in JUnit, when should I use assertEquals() when should I use try...catch to verify results?
例如,在下面代码的 verifySthIsSetCorrectly()
中,我应该使用 assertEquals()
来检查结果还是应该抛出异常以便它被调用者的 try...catch
捕获并让调用者处理?
@Parameters
public static Collection<object[]> methodParams() {
List<Object[]> params = new ArrayList<Object[]>();
/* arg, errorString */
params.add(new Object[] {"arg1", null /*errorString*/});
params.add(new Object[] {"arg2", ERROR_STRING1 /*errorString*/});
}
@Test
public void sampleTest () {
try {
MethodAndWait(arg);
assertNull("expect error String" + errorString, errorString);
} catch (Exception ex) {
assertNotNull("expect error String" + errorString, errorString);
assertTrue(ex.getMessage().contains(errorString));
}
}
private void MethodAndWait() {
call_remote_server_to_have_sth_set;
verifySthIsSetCorrectly();
}
private void verifySthIsSetCorrectly() {
int sth = getSth();
assertEquals(sth == "5");
}
你的测试应该是
@Test
public void sampleTest () {
call_remote_server_to_have_sth_set;
int sth = getSth();
assertEquals(5, sth);
}
如果您还没有读过 JUnit 测试简介,我建议您阅读一下。
在 JUnit 测试中,您应该使用像 assertEquals()
这样的断言来验证方法调用的结果或对象的状态:
@Test
public void addingTwoNumbersShouldWork() {
int result = calculator.add(5, 7);
assertEquals(12, result);
assertFalse(calculator.hasOverflow());
}
在 JUnit 测试中很少使用 try
和 catch
除了测试代码块抛出预期的异常之外的任何事情:
@Test
public void setColorShouldThrowNullPointerExceptionOnNullInput() {
try {
deathRay.setColor(null);
fail("expected NullPointerException");
} catch (NullPointerException expected) {
assertThat(expected.getMessage(), contains("death ray color"));
}
}
如果您正在测试的方法恰好抛出异常,则不需要使用 try
和 catch
:
@Test
public void fireDeathRay() throws DeathRayException {
deathRay.fire();
}
在上面的测试中,如果 fire()
抛出 DeathRayException
(或运行时异常),fireDeathRay
测试将失败。
在JUnit4中,使用try
和catch
的情况就更少见了,因为you can use the ExpectedException
rule to check if a call throws an expected exception.
我将在我的答案被接受后采取不寻常的步骤添加另一个答案。之前的回答主要集中在总结提出的问题上,但我想集中在代码上。
我认为您想知道该怎么做的原因之一是因为测试 sampleTest()
正在测试两个完全不同的东西。 您的测试方法是在同一测试方法中测试正常行为和异常行为。
相反,将异常情况的测试拆分到它们自己的测试方法中。例如:
@RunWith(JUnit4.class)
public class SampleTest {
@Test
public void methodAndWaitShouldAcceptNonNullValue() {
ClassUnderTest.methodAndWait("arg1")
}
@Test
public void methodAndWaitShouldThrowWhenGivenNullValue() {
try {
ClassUnderTest.methodAndWait(null);
fail("NullPointerException was not thrown");
} catch (NullPointerException ex) {
assertTrue(ex.getMessage().contains(ERROR_STRING1));
}
}
}
这有几个优点:
- 如果
methodAndWait("arg1")
抛出异常,测试将失败并显示有用的堆栈跟踪
- 如果
methodAndWait(null)
抛出 NullPointerException
以外的东西,测试将失败并显示有用的堆栈跟踪
- 如果
methodAndWait(null)
没有抛出任何东西,测试将失败并显示一条有用的消息
- 两个测试的意图都很明确
如果需要使用多个参数进行测试,可以使用 Enclosed
runner:
@RunWith(Enclosed.class)
public class SampleTest {
@RunWith(Parameterized.class)
public static class WhenPassingNonNull {
@Parameters
public static Collection<object[]> methodParams() {
List<Object[]> params = new ArrayList<Object[]>();
/* arg, errorString */
params.add(new Object[] {"arg1", "result1"});
params.add(new Object[] {"arg3", "result3"});
}
public final String arg;
public final String actualResult;
public SampleTest(String arg, String actualResult) {
this.arg = arg;
this.actualResult = actualResult;
}
@Test
public void sampleTest() {
String actualResult = ClassUnderTest.methodAndWait(arg);
assertEquals(expectedResult, actualResult);
}
}
@RunWith(JUnit4.class)
public static class WhenPassingNull {
@Test
public void shouldThrowNullPointerException() {
try {
ClassUnderTest.methodAndWait(null);
fail();
} catch (NullPointerException ex) {
assertTrue(ex.getMessage().contains(ERROR_STRING1));
}
}
}
}
例如,在下面代码的 verifySthIsSetCorrectly()
中,我应该使用 assertEquals()
来检查结果还是应该抛出异常以便它被调用者的 try...catch
捕获并让调用者处理?
@Parameters
public static Collection<object[]> methodParams() {
List<Object[]> params = new ArrayList<Object[]>();
/* arg, errorString */
params.add(new Object[] {"arg1", null /*errorString*/});
params.add(new Object[] {"arg2", ERROR_STRING1 /*errorString*/});
}
@Test
public void sampleTest () {
try {
MethodAndWait(arg);
assertNull("expect error String" + errorString, errorString);
} catch (Exception ex) {
assertNotNull("expect error String" + errorString, errorString);
assertTrue(ex.getMessage().contains(errorString));
}
}
private void MethodAndWait() {
call_remote_server_to_have_sth_set;
verifySthIsSetCorrectly();
}
private void verifySthIsSetCorrectly() {
int sth = getSth();
assertEquals(sth == "5");
}
你的测试应该是
@Test
public void sampleTest () {
call_remote_server_to_have_sth_set;
int sth = getSth();
assertEquals(5, sth);
}
如果您还没有读过 JUnit 测试简介,我建议您阅读一下。
在 JUnit 测试中,您应该使用像 assertEquals()
这样的断言来验证方法调用的结果或对象的状态:
@Test
public void addingTwoNumbersShouldWork() {
int result = calculator.add(5, 7);
assertEquals(12, result);
assertFalse(calculator.hasOverflow());
}
在 JUnit 测试中很少使用 try
和 catch
除了测试代码块抛出预期的异常之外的任何事情:
@Test
public void setColorShouldThrowNullPointerExceptionOnNullInput() {
try {
deathRay.setColor(null);
fail("expected NullPointerException");
} catch (NullPointerException expected) {
assertThat(expected.getMessage(), contains("death ray color"));
}
}
如果您正在测试的方法恰好抛出异常,则不需要使用 try
和 catch
:
@Test
public void fireDeathRay() throws DeathRayException {
deathRay.fire();
}
在上面的测试中,如果 fire()
抛出 DeathRayException
(或运行时异常),fireDeathRay
测试将失败。
在JUnit4中,使用try
和catch
的情况就更少见了,因为you can use the ExpectedException
rule to check if a call throws an expected exception.
我将在我的答案被接受后采取不寻常的步骤添加另一个答案。之前的回答主要集中在总结提出的问题上,但我想集中在代码上。
我认为您想知道该怎么做的原因之一是因为测试 sampleTest()
正在测试两个完全不同的东西。 您的测试方法是在同一测试方法中测试正常行为和异常行为。
相反,将异常情况的测试拆分到它们自己的测试方法中。例如:
@RunWith(JUnit4.class)
public class SampleTest {
@Test
public void methodAndWaitShouldAcceptNonNullValue() {
ClassUnderTest.methodAndWait("arg1")
}
@Test
public void methodAndWaitShouldThrowWhenGivenNullValue() {
try {
ClassUnderTest.methodAndWait(null);
fail("NullPointerException was not thrown");
} catch (NullPointerException ex) {
assertTrue(ex.getMessage().contains(ERROR_STRING1));
}
}
}
这有几个优点:
- 如果
methodAndWait("arg1")
抛出异常,测试将失败并显示有用的堆栈跟踪 - 如果
methodAndWait(null)
抛出NullPointerException
以外的东西,测试将失败并显示有用的堆栈跟踪 - 如果
methodAndWait(null)
没有抛出任何东西,测试将失败并显示一条有用的消息 - 两个测试的意图都很明确
如果需要使用多个参数进行测试,可以使用 Enclosed
runner:
@RunWith(Enclosed.class)
public class SampleTest {
@RunWith(Parameterized.class)
public static class WhenPassingNonNull {
@Parameters
public static Collection<object[]> methodParams() {
List<Object[]> params = new ArrayList<Object[]>();
/* arg, errorString */
params.add(new Object[] {"arg1", "result1"});
params.add(new Object[] {"arg3", "result3"});
}
public final String arg;
public final String actualResult;
public SampleTest(String arg, String actualResult) {
this.arg = arg;
this.actualResult = actualResult;
}
@Test
public void sampleTest() {
String actualResult = ClassUnderTest.methodAndWait(arg);
assertEquals(expectedResult, actualResult);
}
}
@RunWith(JUnit4.class)
public static class WhenPassingNull {
@Test
public void shouldThrowNullPointerException() {
try {
ClassUnderTest.methodAndWait(null);
fail();
} catch (NullPointerException ex) {
assertTrue(ex.getMessage().contains(ERROR_STRING1));
}
}
}
}