英文:
org.opentest4j.AssertionFailedError: Unexpected exception type thrown ==> expected
问题
我正在尝试测试一个名为sendEmail
的方法。我想对这个方法进行负面测试。我希望捕捉IllegalStateException
的情况。sendEmail
方法位于我的ServiceClient
类中。在测试中,我正在模拟serviceClient
和apiClient
,方法的代码如下:
public HttpStatus sendEmail(){
Supplier<HttpStatus> apiRequest = apiclient.post(command);
return retry(apiRequest).orElseThrow(() -> new IllegalStateException());
}
private <T> Optional<T> retry(Supplier<T> apiRequest) {
T result = apiRequest.get();
if (result != null) {
return Optional.of(result);
}
result = apiRequest.get();
if (result != null) {
return Optional.of(result);
}
return Optional.empty();
}
我试图运行的测试如下所示:
@Test
void sendEmailShouldThrowIllegalStateException() {
when(apiclient.post(any())).thenReturn(null, null);
assertThrows(IllegalStateException.class,
() -> serviceClient.sendEndpointRegistrationEmail());
}
我认为这会起作用,因为模拟方法应该返回null
,从而触发异常,但实际上抛出了以下错误:
org.opentest4j.AssertionFailedError: Unexpected exception type thrown ==> expected: <java.lang.IllegalStateException> but was: <java.lang.NullPointerException>
只是为了澄清问题,并不是我得到了空指针异常。问题在于抛出了错误的异常。
英文:
I am trying to test a method sendEmail
. I would like to do a negative test on the method. I want to catch the IllegalStateException
case. The sendemail
method is in my ServiceClient class. In the test I am mocking serviceClient
and apiClient
the code for the method looks like this:
public HttpStatus sendEmail(){
Supplier<HttpStatus> apiRequest = apiclient.post(command);
return retry(apiRequest).orElseThrow(() -> new IllegalStateException());
}
private <T> Optional<T> retry(Supplier<T> apiRequest) {
T result = apiRequest.get();
if (result != null) {
return Optional.of(result);
}
result = apiRequest.get();
if (result != null) {
return Optional.of(result);
}
return Optional.empty();
}
The test that I am trying to run looks like this
@Test
void sendEmailShouldThrowIllegalStateException() {
when(apiclient.post(any())
.thenReturn(null, null);
assertThrows(IllegalStateException.class,
() -> serviceClient
.sendEndpointRegistrationEmail());
}
I thought this would work because the mock method should return null
which would trigger the exception, but it throws
org.opentest4j.AssertionFailedError: Unexpected exception type thrown ==> expected: <java.lang.IllegalStateException> but was: <java.lang.NullPointerException>
Just to clarify the issue isn't that I'm getting a NPE. The issue is that the wrong exception is being thrown.
答案1
得分: 1
实际上,所报告的异常 NullPointerException
是相当自然的。
以下是通过您的代码发生的情况:
- 您指示
apiclient
模拟在调用#post
方法时返回null
。 - 在您的测试固件中,您使用已经注入了
apiclient
模拟的serviceClient
调用了serviceClient#sendEndpointRegistrationEmail
。 - 当上述方法被调用时,将导致调用带有空参数
apiRequest
的retry(Supplier<T> apiRequest)
。 T result = apiRequest.get();
随后会导致NPE
,因为apiRequest
为空。
解决方案将是为任何 apiclient.post(any())
调用返回一个模拟,并在调用 Supplier<HttpStatus>#get
时配置后者返回 null
:
@Test
public void sendEmailShouldThrowIllegalStateException() {
// 为您的请求结果创建一个 Supplier 模拟
Supplier apiRequestMock = Mockito.mock(Supplier.class);
when(apiRequestMock.get()).thenReturn(null);
// 将 Supplier 模拟用作返回结果
when(apiclient.post(any())).thenReturn(apiRequestMock);
assertThrows(IllegalStateException.class,
() -> serviceClient
.sendEndpointRegistrationEmail());
}
英文:
Actually the reported exception, NullPointerException
is quite natural.
Here down what is happening through your code:
- You instructed the
apiclient
mock to returnnull
whenever the#post
method is called - Within your test fixture, you called
serviceClient#sendEndpointRegistrationEmail
withserviceClient
(already having theapiclient
mock injected I guess) - When the above method is called, it will result in a call to
retry(Supplier<T> apiRequest)
withapiRequest
argument being null (the result of your mocked call) T result = apiRequest.get();
would then result in aNPE
asapiRequest
is null
The solution would then be to return a mock for any apiclient.post(any())
call and configure the later to return null
when Supplier<HttpStatus>#get
is called:
<!-- language: lang-java -->
@Test
public void sendEmailShouldThrowIllegalStateException() {
// create a Supplier mock for your request result
Supplier apiRequestMock = Mockito.mock(Supplier.class);
when(apiRequestMock.get()).thenReturn(null);
// use the Supplier mock as return result
when(apiclient.post(any())).thenReturn(apiRequestMock);
assertThrows(IllegalStateException.class,
() -> serviceClient
.sendEndpointRegistrationEmail());
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论