在 1 个测试方法中使用 junit @Rule、expectMessage()、匹配器处理多个异常
Using junit @Rule, expectMessage(), matcher for multipe exception in 1 tested method
在我的 Android 项目中,我想使用相同的 @Test 测试一个 class 可以多次抛出不同消息的相同异常。
我希望我的测试通过给定的消息列表并通过其他消息列表。
对 Junit 进行了一些研究,我尝试使用 @Rule
、expectMessage()
和 Hamcrest matcher.
来实现它
我的实施目前基于 "Custom matcher" 描述的 here。
@RunWith(AndroidJUnit4.class)
public class TestException extends ApplicationTestCase {
@Rule public ExpectedException thrown= ExpectedException.none();
public TestException(){
super(AplicatyApplication.class);
}
@Test
public void testException() throws Exception {
thrown.expect(IndexOutOfBoundsException.class);
thrown.expectMessage(new MatchesPattern("*"));
Dummy.exec(0);
// do more stuff here ...
Dummy.exec(1);
// ...
Dummy.exec(2);
// ...
Dummy.exec(3); // I want my test to fail here
// ...
}
class MatchesPattern extends TypeSafeMatcher<String> {
private String pattern;
public MatchesPattern(String pattern) {
this.pattern = pattern;
}
@Override
protected boolean matchesSafely(String item) {
return item.matches(pattern)
&&
item.startsWith("My message")
&& (
item.endsWith("1")
||
item.endsWith("2")
);
}
@Override
public void describeTo(Description description) {
description.appendText("matches pattern ").appendValue(pattern);
}
@Override
protected void describeMismatchSafely(String item, Description mismatchDescription) {
mismatchDescription.appendText("does not match");
}
}
static class Dummy {
static void exec(int i){
if(i == 0)
return;
if(i == 1)
throw new IndexOutOfBoundsException("My message1");
if(i == 2)
throw new IndexOutOfBoundsException("My message2");
if(i == 3)
throw new IndexOutOfBoundsException("My message3");
}
}
}
运行 这个测试我可以看到匹配器只被调用一次,执行 Dummy.exec(1);
.
matchesSafely(String item)
returns true
并且测试以状态 通过 结束。
根据我对@Rule 的理解,所有这些似乎都可以。我在等待一个例外:我明白了;我正在等待给定的消息:我收到了。
一旦抛出第一个异常,我就找不到继续执行测试的方法。
我的问题是:
- 是否可以使用@Rule 检查一个测试方法中抛出的多个异常,还是我必须使用典型的try/catch 测试每个 catch 块中的异常消息?
- 是否有 another/more 优雅的方法来测试此类问题。
我建议将测试方法拆分成多个测试,每个需求一个。
@Test
public void testException_1() throws Exception {
thrown.expect(IndexOutOfBoundsException.class);
thrown.expectMessage("My message1");
Dummy.exec(1);
}
如果它需要在一种测试方法中,我会用 try-catch 和 ErrorCollector 构建它。
@Test
public void testException_1() throws Exception {
try {
Dummy.exec(1);
fail();
} catch (IndexOutOfBoundsException e) {
errorCollector.checkThat(e.getMessage(), is("My message1"));
}
try {
Dummy.exec(2);
...
} ...
}
我会尽量避免构建自定义匹配器。
在我的 Android 项目中,我想使用相同的 @Test 测试一个 class 可以多次抛出不同消息的相同异常。 我希望我的测试通过给定的消息列表并通过其他消息列表。
对 Junit 进行了一些研究,我尝试使用 @Rule
、expectMessage()
和 Hamcrest matcher.
我的实施目前基于 "Custom matcher" 描述的 here。
@RunWith(AndroidJUnit4.class)
public class TestException extends ApplicationTestCase {
@Rule public ExpectedException thrown= ExpectedException.none();
public TestException(){
super(AplicatyApplication.class);
}
@Test
public void testException() throws Exception {
thrown.expect(IndexOutOfBoundsException.class);
thrown.expectMessage(new MatchesPattern("*"));
Dummy.exec(0);
// do more stuff here ...
Dummy.exec(1);
// ...
Dummy.exec(2);
// ...
Dummy.exec(3); // I want my test to fail here
// ...
}
class MatchesPattern extends TypeSafeMatcher<String> {
private String pattern;
public MatchesPattern(String pattern) {
this.pattern = pattern;
}
@Override
protected boolean matchesSafely(String item) {
return item.matches(pattern)
&&
item.startsWith("My message")
&& (
item.endsWith("1")
||
item.endsWith("2")
);
}
@Override
public void describeTo(Description description) {
description.appendText("matches pattern ").appendValue(pattern);
}
@Override
protected void describeMismatchSafely(String item, Description mismatchDescription) {
mismatchDescription.appendText("does not match");
}
}
static class Dummy {
static void exec(int i){
if(i == 0)
return;
if(i == 1)
throw new IndexOutOfBoundsException("My message1");
if(i == 2)
throw new IndexOutOfBoundsException("My message2");
if(i == 3)
throw new IndexOutOfBoundsException("My message3");
}
}
}
运行 这个测试我可以看到匹配器只被调用一次,执行 Dummy.exec(1);
.
matchesSafely(String item)
returns true
并且测试以状态 通过 结束。
根据我对@Rule 的理解,所有这些似乎都可以。我在等待一个例外:我明白了;我正在等待给定的消息:我收到了。
一旦抛出第一个异常,我就找不到继续执行测试的方法。
我的问题是:
- 是否可以使用@Rule 检查一个测试方法中抛出的多个异常,还是我必须使用典型的try/catch 测试每个 catch 块中的异常消息?
- 是否有 another/more 优雅的方法来测试此类问题。
我建议将测试方法拆分成多个测试,每个需求一个。
@Test
public void testException_1() throws Exception {
thrown.expect(IndexOutOfBoundsException.class);
thrown.expectMessage("My message1");
Dummy.exec(1);
}
如果它需要在一种测试方法中,我会用 try-catch 和 ErrorCollector 构建它。
@Test
public void testException_1() throws Exception {
try {
Dummy.exec(1);
fail();
} catch (IndexOutOfBoundsException e) {
errorCollector.checkThat(e.getMessage(), is("My message1"));
}
try {
Dummy.exec(2);
...
} ...
}
我会尽量避免构建自定义匹配器。