[英]How to mock method in Mono.flatMap()?
I write unit tests for some service and I don't understand, why some method that i mock don't call.我为某些服务编写单元测试,但我不明白,为什么我模拟的某些方法不调用。 I try to test
testDeleteDeviceWhenDeviceNotFound()
method and it's pass, but when I try testDeleteDeviceSuccess()
I have problems我尝试测试
testDeleteDeviceWhenDeviceNotFound()
方法并且它通过了,但是当我尝试testDeleteDeviceSuccess()
我有问题
@Service
@Slf4j
@AllArgsConstructor
public class DeviceService {
private DeviceRepository deviceRepository;
private SyncSender syncSender;
public Mono<Void> deleteDevice(long deviceId) {
return deviceRepository
.findById(deviceId)
.switchIfEmpty(Mono.error(new NotFoundException()))
.flatMap(existingDevice -> deviceRepository
.delete(existingDevice)
.then(syncSender.sendDeviceDelete(existingDevice.getDeviceId()))
);
}
} and myTest和 myTest
@ExtendWith(MockitoExtension.class)
class DeviceServiceTest {
@Mock
private DeviceRepository deviceRepository;
@Mock
private SyncSender syncSender;
@InjectMocks
private DeviceService deviceService;
@Test
@DisplayName("Test deleteDevice when NotFoundException")
void testDeleteDeviceWhenDeviceNotFound() {
long deviceId = 100L;
Mockito.when(deviceRepository.findById(deviceId)).thenReturn(Mono.empty());
Mono<Void> mono = deviceService.deleteDevice(deviceId);
StepVerifier
.create(mono)
.expectErrorMatches(throwable -> throwable instanceof NotFoundException)
.verify();
}
@Test
@DisplayName("Test deleteDevice success")
void testDeleteDeviceSuccess() {
DeviceModel deviceModel = createDeviceModel();
deviceModel.setDeviceId(100L);
Mockito.when(deviceRepository.findById(deviceModel.getDeviceId())).thenReturn(Mono.just(deviceModel));
Mockito.when(syncSender.sendDeviceDelete(anyLong())).thenReturn(Mono.empty());
Mockito.when(deviceRepository.delete(any(DeviceModel.class))).thenReturn(Mono.empty());
deviceService.deleteDevice(deviceModel.getDeviceId());
}
}
Exceptions from junit that one of the stubbed methods were never realized in the code under test, during test execution来自 junit 的异常,即在测试执行期间,在被测代码中从未实现存根方法之一
org.mockito.exceptions.misusing.UnnecessaryStubbingException:
Unnecessary stubbings detected.
Clean & maintainable test code requires zero unnecessary code.
Following stubbings are unnecessary (click to navigate to relevant line of code):
1. -> at com.ecosoft.dms.device.vending.service.DeviceServiceTest.testDeleteDeviceSuccess(DeviceServiceTest.java:172)
2. -> at com.ecosoft.dms.device.vending.service.DeviceServiceTest.testDeleteDeviceSuccess(DeviceServiceTest.java:173)
Please remove unnecessary stubbings or use 'lenient' strictness. More info: javadoc for UnnecessaryStubbingException class.
And when I try debug mode I see that I return on this step.Why?当我尝试调试模式时,我看到我回到了这一步。为什么?
.flatMap(existingDevice -> deviceRepository
In your failing test, you have:在你失败的测试中,你有:
deviceService.deleteDevice(deviceModel.getDeviceId());
This creates a mono, but never launches underlying async tasks.这将创建一个 mono,但从不启动底层异步任务。 The test finishes, and Mockito correctly reports that stubbed methods were never called.
测试完成,并且 Mockito 正确报告从未调用存根方法。
You used a StepVerifier in your other test, to my eyes you need to use it here as well to trigger underlying async operations您在其他测试中使用了 StepVerifier,在我看来,您还需要在这里使用它来触发底层异步操作
StepVerifier.create(deviceService.deleteDevice(deviceModel.getDeviceId()))
.verifyComplete();
Check simpler examples:检查更简单的示例:
@Test
void testMonoNotRun() {
Mono.fromCallable(() -> {
System.out.println("Callable run");
return 1;
});
}
@Test
void testMonoRunBySubscribe() {
Mono.fromCallable(() -> {
System.out.println("Callable run");
return 1;
}).subscribe();
}
@Test
void testMonoRunByStepVerify() {
StepVerifier.create(Mono.fromCallable(() -> {
System.out.println("Callable run");
return 1;
})).verifyComplete();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.