有没有更优雅的方法在Android中执行断言抛出异常呢?
public void testGetNonExistingKey() {
try {
alarm.getValue("NotExistingValue");
fail( );
} catch (ElementNotFoundException e) {
}
}
这样的东西不起作用?!
@Test(expected=ElementNotFoundException .class)
谢谢,Mark
答案 0 :(得分:4)
您使用的是junit4测试跑步者吗?如果您正在运行junit3测试运行器,则@Test注释将不起作用。检查您正在使用的版本。
其次,在代码中检查异常的推荐方法是使用规则(在junit 4.7中引入)。
@Rule
public ExpectedException exception = ExpectedException.none();
@Test
public void throwsIllegalArgumentExceptionIfIconIsNull() {
// do something
exception.expect(IllegalArgumentException.class);
exception.expectMessage("Icon is null, not a file, or doesn't exist.");
new DigitalAssetManager(null, null);
}
您可以继续使用@Test(expected = IOException.class),但上面的优点是,如果在调用exception.expect之前抛出异常,则测试将失败。
答案 1 :(得分:3)
我做了一些与hopia's answer非常相似的事情并做了一些改进。我让它返回异常对象,以便您可以检查其消息或任何其他属性,并且我声明了Testable
接口来替换Runnable
,因为Runnable
不允许您的代码受到测试抛出已检查的异常。
public interface Testable {
public void run() throws Exception;
}
public <T extends Exception> T assertThrows(
final Class<T> expected,
final Testable codeUnderTest) throws Exception {
T result = null;
try {
codeUnderTest.run();
fail("Expecting exception but none was thrown.");
} catch(final Exception actual) {
if (expected.isInstance(actual)) {
result = expected.cast(actual);
}
else {
throw actual;
}
}
return result;
}
以下是调用它的示例。
InvalidWordException ex = assertThrows(
InvalidWordException.class,
new Testable() {
@Override
public void run() throws Exception {
model.makeWord("FORG", player2);
}
});
assertEquals(
"message",
"FORG is not in the dictionary.",
ex.getMessage());
答案 2 :(得分:2)
我就是这样做的。我创建了一个名为assertThrowsException的静态方法,它接受一个预期的异常类和一个包含被测试代码的Runnable作为参数。
import junit.framework.Assert;
public SpecialAsserts {
public void assertThrowsException(final Class<? extends Exception> expected, final Runnable codeUnderTest) {
try {
codeUnderTest.run();
Assert.fail("Expecting exception but none was thrown.");
} catch(final Throwable result) {
if (!expected.isInstance(result)) {
Assert.fail("Exception was thrown was unexpected.");
}
}
}
}
这是在测试类中使用特殊断言的示例代码(扩展AndroidTestCase或其衍生产品之一):
public void testShouldThrowInvalidParameterException() {
SpecialAsserts.assertThrowsException(InvalidParameterException.class, new Runnable() {
public void run() {
callFuncThatShouldThrow();
}
});
}
是的,有很多工作,但它比将junit4移植到android更好。
答案 3 :(得分:0)
使用junit3可能会有所帮助。
public static void assertThrows(Class<? extends Throwable> expected,
Runnable runnable) {
try {
runnable.run();
} catch (Throwable t) {
if (!expected.isInstance(t)) {
Assert.fail("Unexpected Throwable thrown.");
}
return;
}
Assert.fail("Expecting thrown Throwable but none thrown.");
}
public static void assertNoThrow(Runnable runnable) {
try {
runnable.run();
} catch (Throwable t) {
Assert.fail("Throwable was unexpectedly thrown.");
}
}
答案 4 :(得分:0)
如果您使用的是Kotlin,则可以利用reified types来避免将Exception子类作为参数传递:
inline fun <reified T : Exception> assertThrows(runnable: () -> Any?) {
try {
runnable.invoke()
} catch (e: Throwable) {
if (e is T) {
return
}
Assert.fail("expected ${T::class.qualifiedName} but caught " +
"${e::class.qualifiedName} instead")
}
Assert.fail("expected ${T::class.qualifiedName}")
}
@Test
fun exampleTest() {
val a = arrayOf(1, 2, 3)
assertThrows<IndexOutOfBoundsException> {
a[5]
}
}