org.opentest4j.AssertionFailedError: 预期发生了意外的异常类型 ==> 期望的是

huangapple go评论72阅读模式
英文:

org.opentest4j.AssertionFailedError: Unexpected exception type thrown ==> expected

问题

我正在尝试测试一个名为sendEmail的方法。我想对这个方法进行负面测试。我希望捕捉IllegalStateException的情况。sendEmail方法位于我的ServiceClient类中。在测试中,我正在模拟serviceClientapiClient,方法的代码如下:

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&lt;HttpStatus&gt; apiRequest = apiclient.post(command);
        return retry(apiRequest).orElseThrow(() -&gt; new IllegalStateException());
}

private &lt;T&gt; Optional&lt;T&gt; retry(Supplier&lt;T&gt; 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,
        () -&gt; 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 ==&gt; expected: &lt;java.lang.IllegalStateException&gt; but was: &lt;java.lang.NullPointerException&gt;

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
  • 当上述方法被调用时,将导致调用带有空参数 apiRequestretry(Supplier&lt;T&gt; apiRequest)
  • T result = apiRequest.get(); 随后会导致 NPE,因为 apiRequest 为空。

解决方案将是为任何 apiclient.post(any()) 调用返回一个模拟,并在调用 Supplier&lt;HttpStatus&gt;#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 return null whenever the #post method is called
  • Within your test fixture, you called serviceClient#sendEndpointRegistrationEmail with serviceClient (already having the apiclient mock injected I guess)
  • When the above method is called, it will result in a call to retry(Supplier&lt;T&gt; apiRequest) with apiRequest argument being null (the result of your mocked call)
  • T result = apiRequest.get(); would then result in a NPE as apiRequest 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&lt;HttpStatus&gt;#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,
      () -&gt; serviceClient
      .sendEndpointRegistrationEmail());
}

huangapple
  • 本文由 发表于 2020年9月25日 22:08:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/64065770.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定