英文:
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
apiclientmock to returnnullwhenever the#postmethod is called - Within your test fixture, you called
serviceClient#sendEndpointRegistrationEmailwithserviceClient(already having theapiclientmock injected I guess) - When the above method is called, it will result in a call to
retry(Supplier<T> apiRequest)withapiRequestargument being null (the result of your mocked call) T result = apiRequest.get();would then result in aNPEasapiRequestis 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());
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论