【问题标题】:NullPointerException when trying to mock response from WebFlux service layer尝试模拟来自 WebFlux 服务层的响应时出现 NullPointerException
【发布时间】:2021-03-17 13:14:47
【问题描述】:

我正在尝试为 WebFlux 应用程序的服务层中的方法编写单元测试,该方法处理另一个服务的响应,该服务进行 REST 调用并返回结果的 Mono。 我已经在自己的单元测试中使用 WebTestClient 测试了嵌套服务,因此我尝试使用 Mockito 模拟它的响应,但遇到 NullPointerException 就好像结果没有被模拟一样。

我对异步/反应模式比较陌生,所以不确定我是否做错了,或者它是否是 Mockito 不能很好地发挥反应的异步性质,但是如果它不是一个嵌套的服务调用,它就可以正常工作嘲讽?

我在一个最小的示例中复制了它,表明它纯粹是对嵌套服务的模拟,它没有按预期工作,其中NestedService.doRestCall() 返回一个Mono<String>

@Service
public class ExampleService {
  private final NestedService nestedService;

  @Autowired
  public ExampleService(final NestedService nestedService) {
    this.nestedService = nestedService;
  }

  public Mono<String> methodToTest() {
    return nestedService.doRestCall()
      .map(data -> data + "-test");
  }
}

还有测试:

@RunWith(SpringRunner.class)
@SpringBootTest
public class ExampleServiceTests {
  @Mock
  private NestedService nestedServiceMock;
  @InjectMocks
  private ExampleService exampleService;

  @Before
  public void setup() {
    MockitoAnnotations.initMocks(this);
  }

  @Test
  public void test() {
    when(nestedServiceMock.doRestCall()).thenReturn(Mono.just("foo"));

    StepVerifier.create(exampleService.methodToTest())
      .expect("foo-test")
      .verifyComplete();
  }
}

我从 ExampleService 行中的 .map() 调用触发了以下 NullPointerException 跟踪,我也尝试过使用 flatMap() 但得到相同的错误:

java.lang.NullPointerException
    at com.example.service.ExampleService.methodToTest(ExampleService.java:18)
    at com.example.service.ExampleServiceTests.test(ExampleServiceTests.java:33)

【问题讨论】:

    标签: java unit-testing mockito spring-webflux


    【解决方案1】:

    你初始化你的模拟两次:

    • 首先由弹簧跑步者
    • 然后由 MockitoAnnotations.initMocks(this);

    让我们用调试器检查setup 方法中的变量:

    initMocks之前:

    nestedServiceMock = {NestedService$MockitoMock$267376363@5567} "nestedServiceMock"
    exampleService = {ExampleService@5568} 
    

    initMocks之后:

    nestedServiceMock = {NestedService$MockitoMock$267376363@5661} "nestedServiceMock"
    exampleService = {ExampleService@5568} 
    exampleService.nestedServiceMock = {NestedService$MockitoMock$267376363@5567} "nestedServiceMock"
    

    您可以清楚地看到 nestedServiceMock 被重新初始化,但 exampleService 没有被重新初始化,并且仍然持有对旧嵌套对象的引用。

    要解决,去掉Spring boot注解。 在这里,使用 JUnit5 的清理版本:

    @ExtendWith(MockitoExtension.class)
    public class ExampleServiceTest {
        @Mock
        private NestedService nestedServiceMock;
        @InjectMocks
        private ExampleService exampleService;
        
        @Test
        public void test() {
            when(nestedServiceMock.doRestCall()).thenReturn(Mono.just("foo"));
    
            StepVerifier.create(exampleService.methodToTest())
                    .expectNext("foo-test")
                    .verifyComplete();
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2020-03-13
      • 2018-10-07
      • 1970-01-01
      • 1970-01-01
      • 2021-04-29
      • 1970-01-01
      • 1970-01-01
      • 2021-02-27
      • 2021-02-11
      相关资源
      最近更新 更多