【发布时间】:2018-05-28 09:53:06
【问题描述】:
我在 Espresso 中有一个测试,需要断言某个操作会导致引发异常。
但是,Espresso 框架似乎吞下了原始异常,只显示了 PerformException。
【问题讨论】:
标签: android unit-testing android-espresso
我在 Espresso 中有一个测试,需要断言某个操作会导致引发异常。
但是,Espresso 框架似乎吞下了原始异常,只显示了 PerformException。
【问题讨论】:
标签: android unit-testing android-espresso
最终我找到了一种方法。 我创建了一个自定义 Hamcrest 匹配器,允许您验证嵌套异常。
public class NestedExceptionMatcher extends TypeSafeMatcher<Throwable> {
private final Class<?> mExpectedType;
private final Matcher<String> mMessageMatcher;
static NestedExceptionMatcher expectNestedThrowable(Class<?> expectedType, Matcher<String> messageMatcher) {
return new NestedExceptionMatcher(expectedType, messageMatcher);
}
NestedExceptionMatcher(Class<?> expectedType, Matcher<String> messageMatcher) {
mExpectedType = expectedType;
mMessageMatcher = messageMatcher;
}
@Override
protected boolean matchesSafely(Throwable item) {
boolean matches = isMatch(item);
Throwable currentThrowable = item.getCause();
while (!matches && currentThrowable != null) {
matches = isMatch(currentThrowable);
currentThrowable = currentThrowable.getCause();
}
return matches;
}
@Override
public void describeTo(Description description) {
description
.appendText("expects type ")
.appendValue(mExpectedType)
.appendText(" with a message ")
.appendDescriptionOf(mMessageMatcher);
}
private boolean isMatch(Throwable t) {
return t.getClass().isAssignableFrom(mExpectedType) && mMessageMatcher.matches(t.getMessage());
}
}
然后你可以在你的测试中使用它:
public class SomeActivityTest {
@Rule
public ActivityTestRule<SomeActivity> mRule = new ActivityTestRule<>(
SomeActivity.class, false, false);
@Rule
public ExpectedException mExceptionRule = ExpectedException.none();
@Test
public void testClick_whenInvalidParamsAreSet_shouldThrowException() {
mRule.launchActivity(getIntentWithInvalidParams());
mExceptionRule.expect(expectNestedThrowable(
IllegalArgumentException.class,
containsString("parameter isn't defined")
));
onView(withId(R.id.my_btn)).perform(click());
}
private Intent getIntentWithInvalidParams() {
...
}
}
【讨论】:
你可以这样做
@Test( expected = ArrayIndexOutOfBoundsException.class) //OR any other
throwable
public void myTest() {
}
【讨论】:
为什么不用这个:
@Test(expected = PerformException::class)
fun traderSummaryContainer_notScroll() {
onView(withId(R.id.traderSummaryContainer))
.perform(scrollTo())
}
【讨论】:
PerformException 是一个包含“有趣”异常的 Espresso 异常。在我发布的示例中,“有趣”的异常是“IllegalArgumentException”
使用正常的 try catch 解决了我的问题,我知道异常是嵌套的。 但是我们仍然可以按原因检查它:
var error: Throwable? = null
try {
onView(something).perform(click())
} catch (e: Throwable) {
error = e;
}
assert(error!!.cause is MySpecificException)
assert(error!!.cause!!.message == "My specific error message")
我已经尝试了上述自定义 Hamcrest 匹配器方法,但我最终得到了不稳定的测试,所以最终移到了这个。
【讨论】:
为什么不使用 Assert.assertThrows(Class expectedThrowable, ThrowingRunnable runnable) 或 Assert.assertThrows(String message, Class expectedThrowable, ThrowingRunnable runnable)
【讨论】: