英文:
Webflux unit testing: call is not going inside .map and .flatMap
问题
我正在为webflux中的calculate函数编写单元测试。
以下是测试用例:
在运行测试用例时,即使dataFromRedis不为空,调用也不会进入.map、.flatMap和.map。有什么我遗漏的吗?
英文:
I am writing unit testing for function calculate in webflux
@Override
public Mono<SearchSessionAndETAResponse> calculate(DTO sessionRequest) throws ExecutionException, InterruptedException {
List<GeospatialData> dataFromRedis = getDataFromRedis(sessionRequest.getSessionId());
return Mono.just(dataFromRedis)
.map(data -> {
System.out.println("data::"+data);
return "entityIdentifiers";
})
.flatMap(entityIdentifiers -> {
System.out.println("entityIdentifiers::"+entityIdentifiers);
return etaService.entitiesEta("entityIdentifiers");
})
.map(wayPointRoute -> {
return searchSessionAndETAResponse;
});
}
below is the test case
@ExtendWith(MockitoExtension.class)
public class BroadCastingServiceImplTest {
@InjectMocks
private BroadCastingServiceImpl broadCastingService;
@Mock
private EtaService etaService;
@BeforeEach
void setUp() {
closeable = MockitoAnnotations.openMocks(this);
}
@AfterEach
void tearDown() throws Exception {
closeable.close();
}
@Test
@DisplayName("Given a valid request, when SearchSession and calculate eta is called, it should search Broadcasting session and return eta")
void givenValidRequest_whenSearchSessionAndCalculateEta_shouldReturnBroadCastingResponseDTO() throws ExecutionException, InterruptedException, IOException {
// GIVEN
UUID sessionId = UUID.randomUUID();
DTO searchSessionAndCalculateETA = new DTO();
searchSessionAndCalculateETA.setSessionId(sessionId.toString());
searchSessionAndCalculateETA.setWaypoints(List.of("waypointsDTO", "waypointsDTO2"));
given(etaService.entitiesEta("entitiesEtaRequestDTO")).willReturn(Mono.just(List.of("entitiesEtaResponseDTO")));
// WHEN
Mono<SearchSessionAndETAResponse> result = broadCastingService.searchSessionAndCalculateETA(searchSessionAndCalculateETA);
}
}
The problem:
when i run test case the call does not go inside .map, .flatMap and .map even though dataFromRedis is not null.
Is there anything i am missing ?
答案1
得分: 1
在你的测试中,你只是创建了 Mono
,但实际上并没有真正地"运行"它,更准确地说,你没有订阅它。
与响应式代码一起工作有两个阶段:
-
首先,你编写响应式流的规范,告诉它要做什么,但不会启动过程。
Mono
只是一个带有许多 lambda 函数的复杂内存结构,告诉它什么时候做什么。 -
然后,你订阅
Mono
- 只有这样才会启动整个过程,并开始调用所有的 lambda。只有在这时,"调用进入 .map 和 .flatMap",用你的话来说
阅读一些教程,例如 Baeldung 的 Reactor Core 入门。
如果你只是在简单的 Spring 应用程序中使用 Mono
来处理 REST 端点,你可能会轻易忽略这一点,因为你的 @RestController
只返回 Mono
,其余的工作由 Spring 处理。Spring 订阅 了你从控制器方法返回的 Mono
,并确保将结果传递给通过 HTTP 调用的对象。
在单元测试中,你可以通过调用其 block()
方法来非常简单地执行,或者更正确地使用 StepVerifier
:
result.as(StepVerifier::create)
.expectNext(objectToExpect)
.verifyComplete();
只使用 block()
方法更像是一种权宜之计。StepVerifier
是正确的单元测试响应式代码的方式。
要小心不要仅仅使用 subscribe()
方法,因为测试可能在订阅有时间执行之前结束,从而导致不可预测的结果。
英文:
In your test you just create the Mono
but you don't actually "run" it, more precisely you do not subscribe to it.
Working with reactive code has two phases:
-
First you write the specification of the reactive stream, which tells what to do, but doesn't start the process. A
Mono
is only a fancy complex memory structure with a lot of lambda functions telling what will be done when it will be done. -
Then you subscribe to the
Mono
- only this starts the whole process and starts calling all the lambdas. Only then the "call is going inside .map and .flatMap" to paraphrase your words
Read some tutorial, e.g. this Baeldung's Intro To Reactor Core.
If you just use Mono
in simple Spring applications to handle REST endpoint, you may easily miss this because your @RestController
just returns the Mono
and the rest (pun intended) is handled by Spring. Spring subscribes to the Mono
you returned from the controller methods and handles that the result is passed to the called via HTTP.
In unit tests, you can do it very simply just by calling its block()
method, or more properly by using StepVerifier
:
result.as(StepVerifier::create)
.expectNext(objectToExpect)
.verifyComplete();
Just using the block()
method works more like a workaround. StepVerifier
is the proper way of unit testing the reactive code.
Be careful not to just use the subscribe()
method, because the test may finish before the subscription has time to perform and you will get unpredictable results.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论