如何测试ExampleRepositoryImpl中的响应式方法getSalers?
Correctly Testing Your Reactive
getSalers Method Let's walk through fixing your test to properly validate the reactive behavior of getSalers, covering both success and error scenarios. Here's what needs adjustment and how to implement it:
Key Issues in Your Current Test
- Reactive streams are lazy: Your test doesn't subscribe to the
Mono, so the actual repository method logic won't execute. - Verify order is wrong: You're calling
verifybefore invoking the method under test. - Missing error case validation: You aren't testing the
switchIfEmptybranch that throwsObjectNotFoundException. - Argument matching might fail: The
CriteriaandQueryinstances you create in the test are different objects than the ones the production code creates, so Mockito won't match them unless you use argument matchers.
Improved Test Implementation
First, add the reactor-test dependency if you haven't already (it's essential for testing reactive code):
<!-- Maven example --> <dependency> <groupId>io.projectreactor</groupId> <artifactId>reactor-test</artifactId> <scope>test</scope> </dependency>
Now, here's the revised test class:
@ExtendWith(MockitoExtension.class) public class ExampleRepositoryImplTest { @Mock ReactiveMongoOperations mongo; ExampleRepositoryImpl exampleRepository; @BeforeEach void setUp() { // No need for spy unless you're verifying internal methods; just inject the mock directly exampleRepository = new ExampleRepositoryImpl(mongo); } @Test void getSalers_WhenDataExists_ReturnsSalersList() { // Arrange int testValue = 5; List<String> expectedSalers = List.of("John", "Jane"); // Use argument matchers to avoid exact object matching issues when(mongo.findDistinct(any(Query.class), eq("salers"), eq(Example.class), eq(String.class))) .thenReturn(Flux.fromIterable(expectedSalers)); // Act & Assert using StepVerifier (critical for reactive tests) StepVerifier.create(exampleRepository.getSalers(testValue)) .expectNext(expectedSalers) // Verify the emitted list .verifyComplete(); // Ensure the stream completes successfully // Verify the mongo method was called once with the right arguments verify(mongo, times(1)) .findDistinct(any(Query.class), eq("salers"), eq(Example.class), eq(String.class)); } @Test void getSalers_WhenNoDataFound_ThrowsObjectNotFoundException() { // Arrange int testValue = 5; when(mongo.findDistinct(any(Query.class), eq("salers"), eq(Example.class), eq(String.class))) .thenReturn(Flux.empty()); // Act & Assert StepVerifier.create(exampleRepository.getSalers(testValue)) .expectError(ObjectNotFoundException.class) // Verify the error is thrown .verify(); verify(mongo, times(1)) .findDistinct(any(Query.class), eq("salers"), eq(Example.class), eq(String.class)); } }
Explanation of Changes
- Removed unnecessary spy: Unless you need to verify internal methods of
ExampleRepositoryImpl, injecting the mock directly is cleaner. - Used
StepVerifier: This is the standard tool for testing reactive streams in Reactor. It subscribes to the stream, asserts emitted values/errors, and verifies stream completion. - Argument matchers: Using
any(Query.class)andeq(...)avoids issues where the test'sQueryinstance doesn't match the one created in production code. If you want to verify the exact criteria, you can use a custom matcher or capture the query to inspect it:// Example: Capture the query to verify criteria ArgumentCaptor<Query> queryCaptor = ArgumentCaptor.forClass(Query.class); verify(mongo).findDistinct(queryCaptor.capture(), eq("salers"), eq(Example.class), eq(String.class)); Query capturedQuery = queryCaptor.getValue(); // Assert the criteria is correct assertThat(capturedQuery.getCriteria()).isEqualTo(Criteria.where("salers").is(testValue)); - Covered both scenarios: We test both when data exists (returns the list) and when no data is found (throws the expected exception).
- Proper verify order:
verifyis called after invoking the method under test, ensuring the interaction has happened.
By following these steps, you'll have a comprehensive test that validates all behaviors of your reactive getSalers method.
内容的提问来源于stack exchange,提问作者MAbarca
相关产品推荐
相关产品推荐

