在Android Espresso测试中断言异常

时间:2018-05-28 09:53:06

标签: android unit-testing android-espresso

我在Espresso中进行了一项测试,需要断言某个操作会导致抛出异常。

然而,似乎Espresso框架吞噬了原始异常并且只显示PerformException

6 个答案:

答案 0 :(得分:3)

最终我找到了办法。 我创建了一个自定义的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() {
        ...
    }
}

答案 1 :(得分:1)

你可以这样做

@Test( expected = ArrayIndexOutOfBoundsException.class) //OR any other  
throwable
public void myTest() {

}

答案 2 :(得分:0)

我使用try / catch块:

try {
    methodThatThrowsException();
    fail("Expected exception not thrown");
} catch (CustomException customException) {
}

答案 3 :(得分:0)

为什么不使用这个:

 @Test(expected = PerformException::class)
    fun traderSummaryContainer_notScroll() {
        onView(withId(R.id.traderSummaryContainer))
                .perform(scrollTo())
    }

答案 4 :(得分:0)

使用正常的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匹配器方法,但是最终我得到了不稳定的测试,因此最终进入了这一测试。

答案 5 :(得分:0)

为什么不使用 Assert.assertThrows(Class expectedThrowable, ThrowingRunnable runnable) 或 Assert.assertThrows(String message, Class expectedThrowable, ThrowingRunnable runnable)