我正在尝试使用内置的Android Junit测试框架编写一些测试。我遇到了一个测试问题,我期待抛出异常。在JUnit中,测试方法的注释将是:
@Test(expected = ArithmeticException.class)
但是,在Android中,此测试因ArithmeticException而失败。
我知道Android实现只是JUnit 3的一个子集,甚至不允许注释@Test(必须是@SmallTest,@ MediumTest或@LargeTest,并且这些都不允许'expected = ..'参数),但这似乎是一个相当重要的测试,如果它没有这个功能,似乎Android测试框架将严重缺乏。
注意:我通过将JUnit jar添加到项目中并通过向我的测试方法添加注释来测试它。对我来说,为什么注释会被完全忽略是有道理的,因为Android框架(runner?)不是在寻找那个注释而只是忽略它。基本上,我只是在框架内寻找“正确”的方式来做到这一点。
答案 0 :(得分:63)
这种测试的标准junit 3成语是:
public void testThatMethodThrowsException()
{
try
{
doSomethingThatShouldThrow();
Assert.fail("Should have thrown Arithmetic exception");
}
catch(ArithmeticException e)
{
//success
}
}
答案 1 :(得分:27)
现在可以通过Android SDK获得JUnit4(请参阅android-test-kit)
更新:它现在是d.android.com的正式官员:
AndroidJUnitRunner是适用于Android的新的非捆绑式测试运行器, 这是Android支持测试库的一部分,可以 通过Android支持存储库下载。新的跑步者包含 GoogleInstrumentationTestRunner的所有改进并增加更多功能 特性:
- JUnit4支持
- 用于访问Instrumentation,Context和Bundle Arguments的Instrumentation Registry
- 测试过滤器@SdkSupress和@RequiresDevice
- 测试超时
- 测试分片
- RunListener支持挂钩到测试运行生命周期
- 活动监控机制ActivityLifecycleMonitorRegistry
所以,JUnit4 style of exception testing使用预期的注释:
@Test(expected= IndexOutOfBoundsException.class)
public void empty() {
new ArrayList<Object>().get(0);
}
或预期的例外规则:
@Rule
public ExpectedException thrown = ExpectedException.none();
@Test
public void shouldTestExceptionMessage() throws IndexOutOfBoundsException {
List<Object> list = new ArrayList<Object>();
thrown.expect(IndexOutOfBoundsException.class);
thrown.expectMessage("Index: 0, Size: 0");
list.get(0); // execution will never get past this line
}
也是可能的。
有关如何设置测试支持库的更多详细信息,请参阅official documentation。
答案 2 :(得分:2)
我一直在寻找一些好的解决方案,但是,没有一个解决方案真正令我满意。因此,我创建了自己的。
public final void assertThrows(VoidFunction v, Class<? extends Exception> e) {
try {
v.call();
} catch (Exception ex) {
if (!ex.getClass().equals(e)) {
Assert.fail();
}
// Do nothing, basically succeeds test if same exception was thrown.
return;
}
// Fails if no exception is thrown by default.
Assert.fail();
}
其中VoidFunction是一个简单的界面:
@FunctionalInterface
public interface VoidFunction {
void call();
}
例如,如下所示:
@Test
public void testFoo() {
assertThrows(() -> foo.bar(null)), NullPointerException.class);
assertThrows(() -> foo.setPositiveInt(-5)), IllegalArgumentException.class);
assertThrows(() -> foo.getObjectAt(-100)), IndexOutOfBoundsException.class);
assertThrows(new VoidFunction() {
@Override
public void call() {
foo.getObjectAt(-100);
}
}, IndexOutOfBoundsException.class); // Success
assertThrows(new VoidFunction() {
@Override
public void call() {
throw new Exception();
}
}, NullPointerException.class); // Fail
}
我在不使用lambda的情况下进行了一次呼叫,这有时更容易理解代码,至少对我而言。 使用简单,它允许在一个方法中捕获多个异常。