Android JUnit测试......如何期待异常

时间:2011-05-06 13:37:07

标签: android testing junit

我正在尝试使用内置的Android Junit测试框架编写一些测试。我遇到了一个测试问题,我期待抛出异常。在JUnit中,测试方法的注释将是:

@Test(expected = ArithmeticException.class)

但是,在Android中,此测试因ArithmeticException而失败。

我知道Android实现只是JUnit 3的一个子集,甚至不允许注释@Test(必须是@SmallTest,@ MediumTest或@LargeTest,并且这些都不允许'expected = ..'参数),但这似乎是一个相当重要的测试,如果它没有这个功能,似乎Android测试框架将严重缺乏。

注意:我通过将JUnit jar添加到项目中并通过向我的测试方法添加注释来测试它。对我来说,为什么注释会被完全忽略是有道理的,因为Android框架(runner?)不是在寻找那个注释而只是忽略它。基本上,我只是在框架内寻找“正确”的方式来做到这一点。

3 个答案:

答案 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的情况下进行了一次呼叫,这有时更容易理解代码,至少对我而言。 使用简单,它允许在一个方法中捕获多个异常。