ChatGPT解决这个技术问题 Extra ChatGPT

Mockito 如何模拟和断言抛出的异常?

我在junit测试中使用mockito。你如何让异常发生然后断言它有(通用伪代码)


N
NilsH

先回答你的第二个问题。如果您使用的是 JUnit 4,则可以使用

@Test(expected=MyException.class)

断言发生了异常。并用 mockito “模拟”异常,使用

when(myMock.doSomething()).thenThrow(new MyException());

当您测试具有某种状态的对象的方法时,这种方法是不可接受的。例如,如果您第二次调用它,则有一个对象方法会引发异常。并且您需要测试以测试它在第二次方法调用期间是否抛出异常,而不是第一次。如果它在第一个方法调用期间(在准备阶段)抛出 MyException,那么它应该会失败测试。但是使用这种方法,我们无法检查在哪个方法调用期间引发了异常。
尽管在这种情况下,我们可以从第一个方法调用中捕获异常并将其包装在 RuntimeException 中。
如果方法 doSomething() 返回类型为 void,这不起作用?
M
MariuszS

BDD 风格解决方案(更新到 Java 8)

单独使用 Mockito 不是处理异常的最佳解决方案,请使用 Mockito 和 Catch-Exception

Mockito + Catch-Exception + AssertJ

given(otherServiceMock.bar()).willThrow(new MyException());

when(() -> myService.foo());

then(caughtException()).isInstanceOf(MyException.class);

示例代码

Mockito + Catch-Exception + Assertj 完整示例

依赖项

eu.codearte.catch-exception:catch-exception:2.0

org.assertj:assertj-core:3.12.2


什么是“捕获异常”?有链接吗?
caughtException 是什么?
知道了,它来自com.googlecode.catchexception.CatchException.caughtException;
D
Daniel Treiber

如果您还想测试异常消息,您可以将 JUnit 的 ExpectedException 与 Mockito 一起使用:

@Rule
public ExpectedException expectedException = ExpectedException.none();

@Test
public void testExceptionMessage() throws Exception {
    expectedException.expect(AnyException.class);
    expectedException.expectMessage("The expected message");

    given(foo.bar()).willThrow(new AnyException("The expected message"));
}

given() 这是从哪里来的?
我也更喜欢使用@Rule,因为这样我可以测试预期的消息或原因或与异常有关的其他内容。为了检查异常的原因,我使用:expectedException.expectCause(Mockito.sameInstance(expectedException)) 或 expectedException.expectCause(Mockito.instanceOf(MyException.class)) 以及其他一些派上用场的方法。
S
Selwyn

2015 年 6 月 19 日的更新答案(如果您使用的是 java 8)

只需使用 assertj

使用 assertj-core-3.0.0 + Java 8 Lambda

@Test
public void shouldThrowIllegalArgumentExceptionWhenPassingBadArg() {
assertThatThrownBy(() -> myService.sumTingWong("badArg"))
                                  .isInstanceOf(IllegalArgumentException.class);
}

参考:http://blog.codeleak.pl/2015/04/junit-testing-exceptions-with-java-8.html


为我工作......我们也可以检查异常消息。assertThatThrownBy(() -> myService.sumTingWong("badArg")).hasMessage("test") .isInstanceOf(IllegalArgumentException.class);
M
Manuel Spigolon

如果您使用的是 JUnit 4 和 Mockito 1.10.x 使用以下命令注释您的测试方法:

@Test(expected = AnyException.class)

并抛出你想要的异常使用:

Mockito.doThrow(new AnyException()).when(obj).callAnyMethod();

D
Duncan Jones

使异常发生如下:

when(obj.someMethod()).thenThrow(new AnException());

通过断言您的测试将引发这样的异常来验证它是否已发生:

@Test(expected = AnException.class)

或者通过正常的模拟验证:

verify(obj).someMethod();

如果您的测试旨在证明中间代码处理异常(即不会从您的测试方法中抛出异常),则需要后一个选项。


verify 调用是否断言异常?
@NilsH 不。但如果 when 子句是正确的,它一定抛出了异常。
如果方法 someMethod() 返回类型为 void,那么它不会像这样工作。有什么方法可以模拟 void 方法的抛出异常?
R
Rodrigo Martins de Oliveira

使用 Mockito's doThrow 然后捕获所需的异常以断言它稍后被抛出。

@Test
public void fooShouldThrowMyException() {
    // given
    val myClass = new MyClass();
    val arg = mock(MyArgument.class);
    doThrow(MyException.class).when(arg).argMethod(any());
    Exception exception = null;

    // when
    try {
        myClass.foo(arg);
    } catch (MyException t) {
        exception = t;
    }

    // then
    assertNotNull(exception);
}

A
Anupama Boorlagadda

使用 mockito,您可以使异常发生。

when(testingClassObj.testSomeMethod).thenThrow(new CustomException());

使用 Junit5,您可以断言异常,断言在调用测试方法时是否抛出该异常。

@Test
@DisplayName("Test assert exception")
void testCustomException(TestInfo testInfo) {
    final ExpectCustomException expectEx = new ExpectCustomException();

     InvalidParameterCountException exception = assertThrows(InvalidParameterCountException.class, () -> {
            expectEx.constructErrorMessage("sample ","error");
        });
    assertEquals("Invalid parametercount: expected=3, passed=2", exception.getMessage());
}

在此处查找示例:assert exception junit


谢谢 !为我工作
C
Chetan Botre

我认为这应该为你做。

assertThrows(someException.class, ()-> mockedServiceReference.someMethod(param1,parme2,..));


J
JediCate

或者,如果您的异常是从类的构造函数中抛出的:

@Rule
public ExpectedException exception = ExpectedException.none();

@Test
public void myTest() {    

    exception.expect(MyException.class);
    CustomClass myClass= mock(CustomClass.class);
    doThrow(new MyException("constructor failed")).when(myClass);  

}

e
eel ghEEz

与 mockito 无关,可以捕获异常并断言其属性。要验证异常确实发生了,请在抛出异常的语句之后的 try 块中声明一个错误条件。


@MariuszS 回复正确回答了您所说的与 Mockito 无关的内容
@pringi谢谢,我看到这个问题既涉及模拟异常又涉及捕获它。我想知道这是否取决于被测代码的任何行为。
S
Sam

通过异常消息断言:

    try {
        MyAgent.getNameByNode("d");
    } catch (Exception e) {
        Assert.assertEquals("Failed to fetch data.", e.getMessage());
    }

这样写的话,在没有抛出异常的情况下,测试还是可以通过的。这是我们首先要避免的