尝试模拟来自 WebFlux 服务层的响应时出现 NullPointerException
NullPointerException when trying to mock response from WebFlux service layer
我正在尝试为 WebFlux 应用程序的服务层中的方法编写单元测试,该方法处理另一个服务的响应,该服务发出 REST 调用并且 returns 结果为 Mono。
我已经在它自己的单元测试中使用 WebTestClient 测试嵌套服务,因此我尝试使用 Mockito 模拟来自它的响应,但遇到 NullPointerException,就好像结果没有被模拟一样。
我对 async/reactive 模式比较陌生,所以不确定我是否做错了,或者 Mockito 是否不能很好地适应反应的异步性质,但是如果它不是嵌套服务,它就可以正常工作被嘲笑的电话?
我在一个最小示例中复制了它,表明它纯粹是对嵌套服务的模拟,它没有按预期工作,其中 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() 但得到了同样的错误:
java.lang.NullPointerException
at com.example.service.ExampleService.methodToTest(ExampleService.java:18)
at com.example.service.ExampleServiceTests.test(ExampleServiceTests.java:33)
您两次初始化模拟:
- 首先由 spring 亚军
- 然后 MockitoAnnotations.initMocks(this);
让我们用调试器检查 setup
方法中的变量:
在initMocks
之前:
nestedServiceMock = {NestedService$MockitoMock7376363@5567} "nestedServiceMock"
exampleService = {ExampleService@5568}
initMocks
之后:
nestedServiceMock = {NestedService$MockitoMock7376363@5661} "nestedServiceMock"
exampleService = {ExampleService@5568}
exampleService.nestedServiceMock = {NestedService$MockitoMock7376363@5567} "nestedServiceMock"
你可以清楚地看到 nestedServiceMock
被重新初始化,但 exampleService
没有,并且仍然持有对旧嵌套对象的引用。
要解决,去掉Spring引导注释。
在这里,使用 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 应用程序的服务层中的方法编写单元测试,该方法处理另一个服务的响应,该服务发出 REST 调用并且 returns 结果为 Mono。 我已经在它自己的单元测试中使用 WebTestClient 测试嵌套服务,因此我尝试使用 Mockito 模拟来自它的响应,但遇到 NullPointerException,就好像结果没有被模拟一样。
我对 async/reactive 模式比较陌生,所以不确定我是否做错了,或者 Mockito 是否不能很好地适应反应的异步性质,但是如果它不是嵌套服务,它就可以正常工作被嘲笑的电话?
我在一个最小示例中复制了它,表明它纯粹是对嵌套服务的模拟,它没有按预期工作,其中 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() 但得到了同样的错误:
java.lang.NullPointerException
at com.example.service.ExampleService.methodToTest(ExampleService.java:18)
at com.example.service.ExampleServiceTests.test(ExampleServiceTests.java:33)
您两次初始化模拟:
- 首先由 spring 亚军
- 然后 MockitoAnnotations.initMocks(this);
让我们用调试器检查 setup
方法中的变量:
在initMocks
之前:
nestedServiceMock = {NestedService$MockitoMock7376363@5567} "nestedServiceMock"
exampleService = {ExampleService@5568}
initMocks
之后:
nestedServiceMock = {NestedService$MockitoMock7376363@5661} "nestedServiceMock"
exampleService = {ExampleService@5568}
exampleService.nestedServiceMock = {NestedService$MockitoMock7376363@5567} "nestedServiceMock"
你可以清楚地看到 nestedServiceMock
被重新初始化,但 exampleService
没有,并且仍然持有对旧嵌套对象的引用。
要解决,去掉Spring引导注释。 在这里,使用 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();
}
}