如何以惯用方式使用JUnit4来测试某些代码是否会抛出异常?
虽然我当然可以这样做:
@Test
public void testFooThrowsIndexOutOfBoundsException() {
boolean thrown = false;
try {
foo.doStuff();
} catch (IndexOutOfBoundsException e) {
thrown = true;
}
assertTrue(thrown);
}
我记得有一个注释或Assert.xyz或某些东西,对于这些情况来说,它远不如KUndgy和JUnit更精神。
答案 0 :(得分:2202)
JUnit 4支持:
@Test(expected = IndexOutOfBoundsException.class)
public void testIndexOutOfBoundsException() {
ArrayList emptyList = new ArrayList();
Object o = emptyList.get(0);
}
答案 1 :(得分:1248)
修改现在JUnit5已经发布,最好的选择是使用Assertions.assertThrows()
(请参阅my other answer)。
如果您尚未迁移到JUnit 5,但可以使用JUnit 4.7,则可以使用ExpectedException
规则:
public class FooTest {
@Rule
public final ExpectedException exception = ExpectedException.none();
@Test
public void doStuffThrowsIndexOutOfBoundsException() {
Foo foo = new Foo();
exception.expect(IndexOutOfBoundsException.class);
foo.doStuff();
}
}
这比@Test(expected=IndexOutOfBoundsException.class)
要好得多,因为如果在IndexOutOfBoundsException
之前抛出foo.doStuff()
,测试将会失败
有关详细信息,请参阅this article
答案 2 :(得分:446)
小心使用预期的异常,因为它只断言方法在测试中抛出了该异常,而不是特定的代码行。
我倾向于使用它来测试参数验证,因为这些方法通常非常简单,但更复杂的测试可能更适合:
try {
methodThatShouldThrow();
fail( "My method didn't throw when I expected it to" );
} catch (MyException expectedException) {
}
判断。
答案 3 :(得分:203)
如前所述,有许多方法可以处理JUnit中的异常。但是对于Java 8,还有另外一个:使用Lambda Expressions。使用Lambda Expressions,我们可以实现这样的语法:
@Test
public void verifiesTypeAndMessage() {
assertThrown(new DummyService()::someMethod)
.isInstanceOf(RuntimeException.class)
.hasMessage("Runtime exception occurred")
.hasMessageStartingWith("Runtime")
.hasMessageEndingWith("occurred")
.hasMessageContaining("exception")
.hasNoCause();
}
assertThrown接受一个功能接口,其实例可以使用lambda表达式,方法引用或构造函数引用创建。 assertThrown接受该接口期望并准备好处理异常。
这是一种相对简单但功能强大的技术。
看一下这篇描述这种技术的博客文章:http://blog.codeleak.pl/2014/07/junit-testing-exception-with-java-8-and-lambda-expressions.html
披露:我是博客和项目的作者。
答案 4 :(得分:109)
使用Test annonation的可选'expected'属性
@Test(expected = IndexOutOfBoundsException.class)
public void testFooThrowsIndexOutOfBoundsException() {
foo.doStuff();
}
,使用ExpectedException规则
public class XxxTest {
@Rule
public ExpectedException thrown = ExpectedException.none();
@Test
public void testFooThrowsIndexOutOfBoundsException() {
thrown.expect(IndexOutOfBoundsException.class)
//you can test the exception message like
thrown.expectMessage("expected messages");
foo.doStuff();
}
}
您还可以使用在junit 3 framework下广泛使用的经典try / catch方式
@Test
public void testFooThrowsIndexOutOfBoundsException() {
try {
foo.doStuff();
fail("expected exception was not occured.");
} catch(IndexOutOfBoundsException e) {
//if execution reaches here,
//it indicates this exception was occured.
//so we need not handle it.
}
}
最后,对于junit5.x,您还可以使用assertThrows,如下所示
@Test
public void testFooThrowsIndexOutOfBoundsException() {
Throwable exception = assertThrows(IndexOutOfBoundsException.class, () -> foo.doStuff());
assertEquals("expected messages", exception.getMessage());
}
所以
有关详细信息,请参阅this document和junit5 user guide了解详情。
答案 5 :(得分:94)
<强> TL;博士强>
JDK8之前:我会推荐旧的try
- catch
块。 (不要忘记在fail()
阻止之前添加catch
断言
post-JDK8:使用AssertJ或自定义lambdas来断言异常行为。
无论是Junit 4还是JUnit 5.
长篇故事
可以自己编写自己动手 try
- catch
阻止或使用JUnit工具(@Test(expected = ...)
或@Rule ExpectedException
JUnit规则功能)。
但是这些方式并不那么优雅,并且不能与其他工具很好地混合可读性。此外,JUnit工具确实存在一些缺陷。
try
- catch
阻止你必须围绕测试行为编写块,并在catch块中写下断言,这可能没什么问题,但是很多人发现这个样式中断了测试的阅读流程。你还需要在Assert.fail
块的末尾写一个try
,否则测试可能会错过断言的一面; PMD , findbugs 或 Sonar 会发现此类问题。
@Test(expected = ...)
功能很有意思,因为您可以编写更少的代码,然后编写此测试可能不太容易出现编码错误。 但这种方法缺乏一些领域。
此外,由于期望在方法中存在,取决于测试代码的编写方式,然后测试代码的错误部分可能抛出异常,导致误报测试,我不确定< em> PMD , findbugs 或 Sonar 将提供有关此类代码的提示。
@Test(expected = WantedException.class)
public void call2_should_throw_a_WantedException__not_call1() {
// init tested
tested.call1(); // may throw a WantedException
// call to be actually tested
tested.call2(); // the call that is supposed to raise an exception
}
ExpectedException
规则也是尝试修复之前的警告,但使用期望样式感觉有点尴尬, EasyMock 用户非常了解这种风格。对某些人来说可能很方便,但是如果你遵循行为驱动开发(BDD)或安排行为断言(AAA)原则,那么ExpectedException
规则就会赢得&#39;适合那些写作风格。除此之外,它可能会遇到与@Test
方式相同的问题,具体取决于您预期的位置。
@Rule ExpectedException thrown = ExpectedException.none()
@Test
public void call2_should_throw_a_WantedException__not_call1() {
// expectations
thrown.expect(WantedException.class);
thrown.expectMessage("boom");
// init tested
tested.call1(); // may throw a WantedException
// call to be actually tested
tested.call2(); // the call that is supposed to raise an exception
}
即使预期的异常放在测试语句之前,如果测试遵循BDD或AAA,它也会破坏您的阅读流程。
另请参阅ExpectedException
作者的JUnit上的comment问题。 JUnit 4.13-beta-2甚至不赞成这种机制:
Pull request #1519:弃用ExpectedException
方法Assert.assertThrows为验证异常提供了一种更好的方法。此外,当与TestWatcher等其他规则一起使用时,ExpectedException的使用容易出错,因为在这种情况下规则的顺序很重要。
因此,上述选项包含所有注意事项,并且显然不会对编码器错误产生影响。
在创建了一个看起来很有前途的答案后,我意识到了一个项目catch-exception。
正如项目描述所说的那样,它让编码器用流畅的代码行编写代码来捕获异常并为以后的断言提供此异常。您可以使用任何断言库,如Hamcrest或AssertJ。
从主页获取的一个快速示例:
// given: an empty list
List myList = new ArrayList();
// when: we try to get the first element of the list
when(myList).get(1);
// then: we expect an IndexOutOfBoundsException
then(caughtException())
.isInstanceOf(IndexOutOfBoundsException.class)
.hasMessage("Index: 1, Size: 0")
.hasNoCause();
正如您所看到的,代码非常简单,您可以在特定行上捕获异常,then
API是将使用AssertJ API的别名(类似于使用assertThat(ex).hasNoCause()...
)。 在某些时候,该项目依赖于FEST-Assert的AssertJ 的祖先。 编辑:该项目似乎正在酝酿Java 8 Lambdas支持。
目前这个图书馆有两个缺点:
在撰写本文时,值得注意的是,该库基于Mockito 1.x,因为它创建了场景背后测试对象的模拟。由于Mockito仍未更新此库无法与最终类或最终方法一起使用。即使它是基于当前版本的mockito 2,这也需要声明一个全局模拟制作者(inline-mock-maker
),这可能不是你想要的东西,因为这个模拟器具有与常规模拟器不同的缺点。
它需要另一个测试依赖。
一旦库支持lambdas,这些问题就不会适用,但AssertJ工具集会复制该功能。
如果您不想使用catch-exception工具,请考虑所有问题,我将推荐try
- catch
块的旧方法,至少直到JDK7。对于JDK 8用户,您可能更喜欢使用AssertJ,因为它提供的可能不仅仅是断言异常。
使用JDK8,lambdas进入测试场景,并且它们被证明是一种断言异常行为的有趣方式。 AssertJ已经更新,提供了一个很好的流畅API来断言异常行为。
使用AssertJ的示例测试:
@Test
public void test_exception_approach_1() {
...
assertThatExceptionOfType(IOException.class)
.isThrownBy(() -> someBadIOOperation())
.withMessage("boom!");
}
@Test
public void test_exception_approach_2() {
...
assertThatThrownBy(() -> someBadIOOperation())
.isInstanceOf(Exception.class)
.hasMessageContaining("boom");
}
@Test
public void test_exception_approach_3() {
...
// when
Throwable thrown = catchThrowable(() -> someBadIOOperation());
// then
assertThat(thrown).isInstanceOf(Exception.class)
.hasMessageContaining("boom");
}
通过几乎完全重写JUnit 5,断言已经improved一点,它们可能被证明是一种开箱即用的方式来断言正确的异常。但真的断言API仍然有点差,assertThrows
以外什么都没有。
@Test
@DisplayName("throws EmptyStackException when peeked")
void throwsExceptionWhenPeeked() {
Throwable t = assertThrows(EmptyStackException.class, () -> stack.peek());
Assertions.assertEquals("...", t.getMessage());
}
正如您所注意到的,assertEquals
仍在返回void
,因此不允许链接断言,如AssertJ。
此外,如果您记得与Matcher
或Assert
发生冲突,请准备好与Assertions
发生冲突。
我想得出结论,今天(2017-03-03) AssertJ 的易用性,可发现的API,快速的开发速度以及作为事实上的测试依赖是JDK8的最佳解决方案,无论测试框架如何(JUnit与否),之前的JDK应该依赖于 try
- catch
块即使他们感到笨拙。
此答案是从another question复制而来的,不具备相同的知名度,我是同一作者。
答案 6 :(得分:49)
现在JUnit 5已经发布,最好的选择是使用Assertions.assertThrows()
(参见
Junit 5 User Guide)。
这是一个验证抛出异常的示例,并使用Truth对异常消息进行断言:
public class FooTest {
@Test
public void doStuffThrowsIndexOutOfBoundsException() {
Foo foo = new Foo();
IndexOutOfBoundsException e = assertThrows(
IndexOutOfBoundsException.class, foo::doStuff);
assertThat(e).hasMessageThat().contains("woops!");
}
}
其他答案中的方法优势是:
throws
子句类似的方法将添加到JUnit 4.13中的org.junit Assert
。
答案 7 :(得分:40)
这个怎么样:捕获一个非常一般的异常,确保它使它脱离catch块,然后声明异常的类是你期望的那样。如果a)异常类型错误(例如,如果你有一个Null Pointer)和b)没有抛出异常,那么这个断言将失败。
public void testFooThrowsIndexOutOfBoundsException() {
Throwable e = null;
try {
foo.doStuff();
} catch (Throwable ex) {
e = ex;
}
assertTrue(e instanceof IndexOutOfBoundsException);
}
答案 8 :(得分:34)
@Test
public void testFooThrowsIndexOutOfBoundsException() {
when(foo).doStuff();
then(caughtException()).isInstanceOf(IndexOutOfBoundsException.class);
}
eu.codearte.catch-exception:catch-exception:1.3.3
答案 9 :(得分:33)
使用AssertJ断言,可与JUnit一起使用:
? (let ((c 10))
(declare (special c))
(eval (read-from-string "`(a b ,c)")))
(A B 10)
它比import static org.assertj.core.api.Assertions.*;
@Test
public void testFooThrowsIndexOutOfBoundsException() {
Foo foo = new Foo();
assertThatThrownBy(() -> foo.doStuff())
.isInstanceOf(IndexOutOfBoundsException.class);
}
更好,因为它可以保证测试中的预期行引发异常并让您检查有关异常的更多详细信息,例如消息,更容易:
@Test(expected=IndexOutOfBoundsException.class)
答案 10 :(得分:32)
为了解决同样的问题,我设置了一个小项目: http://code.google.com/p/catch-exception/
使用这个小助手你会写
verifyException(foo, IndexOutOfBoundsException.class).doStuff();
这比JUnit 4.7的ExpectedException规则简洁得多。 与skaffman提供的解决方案相比,您可以指定您期望异常的代码行。我希望这会有所帮助。
答案 11 :(得分:29)
更新:JUnit5对异常测试有所改进:assertThrows
。
以下示例来自:Junit 5 User Guide
@Test
void exceptionTesting() {
Throwable exception = assertThrows(IllegalArgumentException.class, () ->
{
throw new IllegalArgumentException("a message");
});
assertEquals("a message", exception.getMessage());
}
使用JUnit 4的原始答案。
有几种方法可以测试抛出异常。我还在帖子How to write great unit tests with JUnit
中讨论了以下选项设置expected
参数@Test(expected = FileNotFoundException.class)
。
@Test(expected = FileNotFoundException.class)
public void testReadFile() {
myClass.readFile("test.txt");
}
使用try
catch
public void testReadFile() {
try {
myClass.readFile("test.txt");
fail("Expected a FileNotFoundException to be thrown");
} catch (FileNotFoundException e) {
assertThat(e.getMessage(), is("The file test.txt does not exist!"));
}
}
使用ExpectedException
规则进行测试。
@Rule
public ExpectedException thrown = ExpectedException.none();
@Test
public void testReadFile() throws FileNotFoundException {
thrown.expect(FileNotFoundException.class);
thrown.expectMessage(startsWith("The file test.txt"));
myClass.readFile("test.txt");
}
您可以在JUnit4 wiki for Exception testing和bad.robot - Expecting Exceptions JUnit Rule中详细了解例外测试。
答案 12 :(得分:21)
你也可以这样做:
@Test
public void testFooThrowsIndexOutOfBoundsException() {
try {
foo.doStuff();
assert false;
} catch (IndexOutOfBoundsException e) {
assert true;
}
}
答案 13 :(得分:13)
恕我直言,在JUnit中检查异常的最佳方法是try / catch / fail / assert模式:
// this try block should be as small as possible,
// as you want to make sure you only catch exceptions from your code
try {
sut.doThing();
fail(); // fail if this does not throw any exception
} catch(MyException e) { // only catch the exception you expect,
// otherwise you may catch an exception for a dependency unexpectedly
// a strong assertion on the message,
// in case the exception comes from anywhere an unexpected line of code,
// especially important if your checking IllegalArgumentExceptions
assertEquals("the message I get", e.getMessage());
}
assertTrue
对某些人来说可能有点强,所以assertThat(e.getMessage(), containsString("the message");
可能更合适。
答案 14 :(得分:12)
import java.util.*;
import java.io.*;
public class Test {
public static void main(String ... args) {
try {
ProcessBuilder launcher = new ProcessBuilder();
Map<String, String> environment = launcher.environment();
launcher.redirectErrorStream(true);
launcher.directory(new File("\\\\remote_machine\\Snaps\\"));
launcher.command("powershell.exe", ".\\Script.ps1");
Process p = launcher.start(); // And launch a new process
BufferedReader stdInput = new BufferedReader(new
InputStreamReader(p.getInputStream()));
String line;
System.out.println("Output :");
while ((line = stdInput.readLine()) != null) {
System.out.println(line);
}
} catch (Exception e){
e.printStackTrace();
}
}
}
上关于JUnit 5的更多信息
答案 15 :(得分:11)
我在这里尝试了很多方法,但它们要么很复杂,要么完全不符合我的要求。实际上,人们可以非常简单地编写辅助方法:
public class ExceptionAssertions {
public static void assertException(BlastContainer blastContainer ) {
boolean caughtException = false;
try {
blastContainer.test();
} catch( Exception e ) {
caughtException = true;
}
if( !caughtException ) {
throw new AssertionFailedError("exception expected to be thrown, but was not");
}
}
public static interface BlastContainer {
public void test() throws Exception;
}
}
像这样使用:
assertException(new BlastContainer() {
@Override
public void test() throws Exception {
doSomethingThatShouldExceptHere();
}
});
零依赖:不需要mockito,不需要powermock;并且在最后的课程中工作得很好。
答案 16 :(得分:10)
我在Mkyong blog找到的Junit 4最灵活,最优雅的答案。它具有@Rule
使用package com.mkyong;
import com.mkyong.examples.CustomerService;
import com.mkyong.examples.exception.NameNotFoundException;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.Matchers.hasProperty;
public class Exception3Test {
@Rule
public ExpectedException thrown = ExpectedException.none();
@Test
public void testNameNotFoundException() throws NameNotFoundException {
//test specific type of exception
thrown.expect(NameNotFoundException.class);
//test message
thrown.expectMessage(is("Name is empty!"));
//test detail
thrown.expect(hasProperty("errCode")); //make sure getters n setters are defined.
thrown.expect(hasProperty("errCode", is(666)));
CustomerService cust = new CustomerService();
cust.findByName("");
}
}
注释的灵活性。我喜欢这种方法,因为您可以阅读自定义异常的特定属性。
REM Search local directories for files, delete if not present on server
set n=0
set count=0
for /f %%a in ('dir /a:d /b %_Entry_Local_Status60_path%') do (
set folder[!n!]=%%a
set /A a+=1
set /A n+=1
set /A count+=1
)
set n=0
for /L %%a in (0,1,%count%) do (
echo !folder[%n%]!
if not exist %_Entry_Network_Status60_path%\!folder[%n%]! rmdir %_Entry_Local_Status60_path%\!folder[%n%]!
set /A n+=1
)
答案 17 :(得分:9)
如果您想要一个解决方案:
这是我写的实用函数:
public final <T extends Throwable> T expectException( Class<T> exceptionClass, Runnable runnable )
{
try
{
runnable.run();
}
catch( Throwable throwable )
{
if( throwable instanceof AssertionError && throwable.getCause() != null )
throwable = throwable.getCause(); //allows "assert x != null : new IllegalArgumentException();"
assert exceptionClass.isInstance( throwable ) : throwable; //exception of the wrong kind was thrown.
assert throwable.getClass() == exceptionClass : throwable; //exception thrown was a subclass, but not the exact class, expected.
@SuppressWarnings( "unchecked" )
T result = (T)throwable;
return result;
}
assert false; //expected exception was not thrown.
return null; //to keep the compiler happy.
}
按如下方式使用:
@Test
public void testThrows()
{
RuntimeException e = expectException( RuntimeException.class, () ->
{
throw new RuntimeException( "fail!" );
} );
assert e.getMessage().equals( "fail!" );
}
答案 18 :(得分:8)
JUnit内置了对"expected" attribute
的支持答案 19 :(得分:7)
在我的情况下,我总是从db获取RuntimeException,但消息不同。并且需要分别处理异常。以下是我测试它的方法:
@Test
public void testThrowsExceptionWhenWrongSku() {
// Given
String articleSimpleSku = "999-999";
int amountOfTransactions = 1;
Exception exception = null;
// When
try {
createNInboundTransactionsForSku(amountOfTransactions, articleSimpleSku);
} catch (RuntimeException e) {
exception = e;
}
// Then
shouldValidateThrowsExceptionWithMessage(exception, MESSAGE_NON_EXISTENT_SKU);
}
private void shouldValidateThrowsExceptionWithMessage(final Exception e, final String message) {
assertNotNull(e);
assertTrue(e.getMessage().contains(message));
}
答案 20 :(得分:5)
在JUnit 4或更高版本中,您可以按如下方式测试例外
@Rule
public ExpectedException exceptions = ExpectedException.none();
这提供了许多可用于改进JUnit测试的功能。
如果您看到以下示例,我正在测试异常中的3件事。
public class MyTest {
@Rule
public ExpectedException exceptions = ExpectedException.none();
ClassUnderTest classUnderTest;
@Before
public void setUp() throws Exception {
classUnderTest = new ClassUnderTest();
}
@Test
public void testAppleisSweetAndRed() throws Exception {
exceptions.expect(Exception.class);
exceptions.expectMessage("this is the exception message");
exceptions.expectCause(Matchers.<Throwable>equalTo(exceptionCause));
classUnderTest.methodUnderTest("param1", "param2");
}
}
答案 21 :(得分:5)
我们可以在必须返回异常的方法之后使用断言失败:
try{
methodThatThrowMyException();
Assert.fail("MyException is not thrown !");
} catch (final Exception exception) {
// Verify if the thrown exception is instance of MyException, otherwise throws an assert failure
assertTrue(exception instanceof MyException, "An exception other than MyException is thrown !");
// In case of verifying the error message
MyException myException = (MyException) exception;
assertEquals("EXPECTED ERROR MESSAGE", myException.getMessage());
}
答案 22 :(得分:5)
只需制作一个可以关闭和打开的匹配器,如下所示:
public class ExceptionMatcher extends BaseMatcher<Throwable> {
private boolean active = true;
private Class<? extends Throwable> throwable;
public ExceptionMatcher(Class<? extends Throwable> throwable) {
this.throwable = throwable;
}
public void on() {
this.active = true;
}
public void off() {
this.active = false;
}
@Override
public boolean matches(Object object) {
return active && throwable.isAssignableFrom(object.getClass());
}
@Override
public void describeTo(Description description) {
description.appendText("not the covered exception type");
}
}
使用它:
添加public ExpectedException exception = ExpectedException.none();
,
然后:
ExceptionMatcher exMatch = new ExceptionMatcher(MyException.class);
exception.expect(exMatch);
someObject.somethingThatThrowsMyException();
exMatch.off();
答案 23 :(得分:4)
除NamShubWriter所说的内容外,请确保:
不执行此操作:
@Rule
public ExpectedException expectedException;
@Before
public void setup()
{
expectedException = ExpectedException.none();
}
最后,this博客文章清楚地说明了如何断言抛出某个异常。
答案 24 :(得分:3)
我推荐库assertj-core
来处理junit测试中的异常
在Java 8中,像这样:
//given
//when
Throwable throwable = catchThrowable(() -> anyService.anyMethod(object));
//then
AnyException anyException = (AnyException) throwable;
assertThat(anyException.getMessage()).isEqualTo("........");
assertThat(exception.getCode()).isEqualTo(".......);
答案 25 :(得分:2)
使用Java8的Junit4解决方案是使用此功能:
public Throwable assertThrows(Class<? extends Throwable> expectedException, java.util.concurrent.Callable<?> funky) {
try {
funky.call();
} catch (Throwable e) {
if (expectedException.isInstance(e)) {
return e;
}
throw new AssertionError(
String.format("Expected [%s] to be thrown, but was [%s]", expectedException, e));
}
throw new AssertionError(
String.format("Expected [%s] to be thrown, but nothing was thrown.", expectedException));
}
然后用法:
assertThrows(ValidationException.class,
() -> finalObject.checkSomething(null));
请注意,唯一的限制是在lambda表达式中使用final
对象引用。
此解决方案允许继续测试断言,而不是期望使用@Test(expected = IndexOutOfBoundsException.class)
解决方案在方法级别上提升。
答案 26 :(得分:1)
例如,您想为下面提到的代码片段
编写Junitpublic int divideByZeroDemo(int a,int b){
return a/b;
}
public void exceptionWithMessage(String [] arr){
throw new ArrayIndexOutOfBoundsException("Array is out of bound");
}
上面的代码是为了测试可能发生的一些未知异常,下面的代码是用自定义消息声明一些异常。
@Rule
public ExpectedException exception=ExpectedException.none();
private Demo demo;
@Before
public void setup(){
demo=new Demo();
}
@Test(expected=ArithmeticException.class)
public void testIfItThrowsAnyException() {
demo.divideByZeroDemo(5, 0);
}
@Test
public void testExceptionWithMessage(){
exception.expectMessage("Array is out of bound");
exception.expect(ArrayIndexOutOfBoundsException.class);
demo.exceptionWithMessage(new String[]{"This","is","a","demo"});
}
答案 27 :(得分:1)
JUnit框架具有 assertThrows()
方法:
ArithmeticException exception = assertThrows(ArithmeticException.class, () ->
calculator.divide(1, 0));
assertEquals("/ by zero", exception.getMessage());
org.junit.jupiter.api.Assertions
类中; org.junit.Assert
类中; org.junit.jupiter:junit-jupiter-api
上添加引用,即可从JUnit 5中获得完美的工作版本。答案 28 :(得分:0)
使用Java 8,您可以创建一个方法,将代码检查并将预期的异常作为参数:
private void expectException(Runnable r, Class<?> clazz) {
try {
r.run();
fail("Expected: " + clazz.getSimpleName() + " but not thrown");
} catch (Exception e) {
if (!clazz.isInstance(e)) fail("Expected: " + clazz.getSimpleName() + " but " + e.getClass().getSimpleName() + " found", e);
}
}
然后在测试中:
expectException(() -> list.sublist(0, 2).get(2), IndexOutOfBoundsException.class);
优点:
答案 29 :(得分:0)
我使用Java 8 lambdas的解决方案:
public static <T extends Throwable> T assertThrows(Class<T> expected, ThrowingRunnable action) throws Throwable {
try {
action.run();
Assert.fail("Did not throw expected " + expected.getSimpleName());
return null; // never actually
} catch (Throwable actual) {
if (!expected.isAssignableFrom(actual.getClass())) { // runtime '!(actual instanceof expected)'
System.err.println("Threw " + actual.getClass().getSimpleName()
+ ", which is not a subtype of expected "
+ expected.getSimpleName());
throw actual; // throw the unexpected Throwable for maximum transparency
} else {
return (T) actual; // return the expected Throwable for further examination
}
}
}
您必须定义一个FunctionalInterface,因为Runnable
没有声明所需的throws
。
@FunctionalInterface
public interface ThrowingRunnable {
void run() throws Throwable;
}
该方法可以如下使用:
class CustomException extends Exception {
public final String message;
public CustomException(final String message) { this.message = message;}
}
CustomException e = assertThrows(CustomException.class, () -> {
throw new CustomException("Lorem Ipsum");
});
assertEquals("Lorem Ipsum", e.message);
答案 30 :(得分:0)
编写测试用例有两种方法
@Test(expected = IndexOutOfBoundsException.class)
您可以使用try catch块在测试类中捕获异常,并对从测试类中的方法抛出的消息进行断言。
try{
}
catch(exception to be thrown from method e)
{
assertEquals("message", e.getmessage());
}
我希望这可以回答您的问题 快乐学习......
答案 31 :(得分:0)
@Test(expectedException=IndexOutOfBoundsException.class)
public void testFooThrowsIndexOutOfBoundsException() throws Exception {
doThrow(IndexOutOfBoundsException.class).when(foo).doStuff();
try {
foo.doStuff();
} catch (IndexOutOfBoundsException e) {
assertEquals(IndexOutOfBoundsException .class, ex.getCause().getClass());
throw e;
}
}
这是检查方法是否抛出正确异常的另一种方法。
答案 32 :(得分:-1)
我想用我的解决方案来评论这个问题,避免了需要任何与异常相关的JUnit代码。
我使用assertTrue(boolean)结合try / catch来查找要抛出的预期异常。这是一个例子:
public void testConstructor() {
boolean expectedExceptionThrown;
try {
// Call constructor with bad arguments
double a = 1;
double b = 2;
double c = a + b; // In my example, this is an invalid option for c
new Triangle(a, b, c);
expectedExceptionThrown = false; // because it successfully constructed the object
}
catch(IllegalArgumentException e) {
expectedExceptionThrown = true; // because I'm in this catch block
}
catch(Exception e) {
expectedExceptionThrown = false; // because it threw an exception but not the one expected
}
assertTrue(expectedExceptionThrown);
}
答案 33 :(得分:-3)
try {
my method();
fail( "This method must thrwo" );
} catch (Exception ex) {
assertThat(ex.getMessage()).isEqual(myErrormsg);
}