尝试模拟来自 WebFlux 服务层的响应时出现 NullPointerException [英] NullPointerException when trying to mock response from WebFlux service layer
问题描述
我正在尝试为 WebFlux 应用程序的服务层中的方法编写单元测试,该方法处理另一个服务的响应,该服务进行 REST 调用并返回结果的 Mono.我已经在它自己的单元测试中使用 WebTestClient 测试嵌套服务,因此我尝试使用 Mockito 模拟它的响应,但遇到 NullPointerException 好像结果没有被模拟一样.
I'm trying to write a unit test for a method in the service layer of a WebFlux application which processes the response of another service that makes a REST call and returns a Mono of the result. I'm already testing the nested service using WebTestClient in it's own unit tests so am trying to mock out the response from it using Mockito but am encountering a NullPointerException as if the result isn't being mocked.
我对 async/reactive 模式比较陌生,所以不确定我是否做错了,或者是 Mockito 没有很好地与 react 的异步性质配合使用,但是如果它不是嵌套的服务调用,它可以正常工作被嘲笑?
I'm relatively new to async/reactive patterns so not sure if I'm doing this wrong or if it's Mockito not playing nicely with the async nature of react however it works fine if it's not a nested service call that is being mocked?
我在一个最小的例子中复制了它,表明它纯粹是对嵌套服务的模拟,它没有按预期工作,其中 NestedService.doRestCall()
返回一个 Mono<字符串>
:
I've replicated it in a minimal example that show's it's purely the mocking of the nested service which isn't working as expected, where NestedService.doRestCall()
returns a 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() 但得到相同的错误:
I get the following NullPointerException trace triggered from the .map() call in the ExampleService line, I've also tried using flatMap() but get the same error:
java.lang.NullPointerException
at com.example.service.ExampleService.methodToTest(ExampleService.java:18)
at com.example.service.ExampleServiceTests.test(ExampleServiceTests.java:33)
推荐答案
你初始化你的模拟两次:
You initialize your mocks twice:
- 第一个由 spring runner
- 然后通过 MockitoAnnotations.initMocks(this);
让我们用调试器检查 setup
方法中的变量:
Lets inspect the variables in the setup
method with debugger:
在 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
没有,并且仍然持有对旧嵌套对象的引用.
You can clearly see that the nestedServiceMock
was re-initialized, but the exampleService
was not, and still holds reference to the old nested object.
解决办法,去掉Spring boot注解.在这里,使用 JUnit5 清理过的版本:
To solve, get rid of Spring boot annotations. Here, cleaned-up version with 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();
}
}
这篇关于尝试模拟来自 WebFlux 服务层的响应时出现 NullPointerException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!