You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何测试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 verify before invoking the method under test.
  • Missing error case validation: You aren't testing the switchIfEmpty branch that throws ObjectNotFoundException.
  • Argument matching might fail: The Criteria and Query instances 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

  1. Removed unnecessary spy: Unless you need to verify internal methods of ExampleRepositoryImpl, injecting the mock directly is cleaner.
  2. 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.
  3. Argument matchers: Using any(Query.class) and eq(...) avoids issues where the test's Query instance 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));
    
  4. Covered both scenarios: We test both when data exists (returns the list) and when no data is found (throws the expected exception).
  5. Proper verify order: verify is 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 15:09:13