使用mockMvc在Junit 5中编写集成测试用例时出现NullPointerException

问题描述 投票:0回答:1

即使所有服务都已注释,也能获取此 NPE 这是代码,我想我也可以得到 EncryptDecryptService 的类似错误,尽管现在还没有得到它

错误

java.lang.NullPointerException: Cannot invoke "comservice.service.SearchService.searchPatient(com.service.requests.SearchPatientRequest)" because "this.patientSearchService" is null
    at com.service.Controller.SearchControllerIntegrationTest.testSearchPatients(SearchControllerIntegrationTest.java:72)

控制器类

RestController
@Slf4j
public class SearchController {
    
    @Autowired
    SearchServiceImpl SearchService;
    @Autowired
    SearchService psService;
    
    @Autowired
    private EncryptDecryptService encryptDecryptService;
    
    @GetMapping("/search")
    public ResponseEntity<SearchResponse> searchPatients(SearchPatientRequest message) {
        SearchResponse response = new SearchResponse();
        try {
            patientSearchService.setEncryptor(encryptDecryptService);
            
            List<Patient> patients = psService.searchPatient(message);
            
            response.setStatus(1);
            
            if (patients.isEmpty()) {
                SearchResponse.Results results = response.getResults();
                results.setPatients(patients);
                response.setResults(results);
            } else {
                SearchResponse.Results results = response.getResults();
                results.setPatients(patients);
                response.setResults(results);
            }
            log.info("PSS search request, Response count: {}", patients.size());
            
        } catch (IllegalArgumentException e) {
            response.setResults(null);
            response.setStatus(0).setErrorMessage(e.getMessage());
        } catch (Throwable e) {
            log.error("PSS Error occurred: {}", e);
            response.setResults(null);
            response.setStatus(0).setErrorMessage("No Patient Found!!");
        }
        return new ResponseEntity(response, HttpStatus.OK);
        
    }
}

测试用例


@ExtendWith(MockitoExtension.class)
@WebMvcTest(SearchController.class)
@AutoConfigureMockMvc
@ActiveProfiles("test")
public class SearchControllerIntegrationTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    SearchServiceImpl patientSearchService;

    @MockBean
    private EncryptDecryptService encryptDecryptService;

    @InjectMocks
    private SearchController patientSearchController;

    private ObjectMapper objectMapper;

    @BeforeEach
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        objectMapper = new ObjectMapper();
    }

    @Test
    public void testSearchPatients() throws Exception {
       
        SearchPatientRequest request = new SearchPatientRequest();
        request.setPatientType("New");
        request.setPatientId("74478");
        when(patientSearchService.searchPatient(any(SearchPatientRequest.class)))
                .thenReturn(Collections.singletonList(new Patient()));

   
        when(encryptDecryptService.encryptString(anyString())).thenReturn("encryptedValue");

        MvcResult result = mockMvc.perform(MockMvcRequestBuilders.get("/search")
                        .contentType(MediaType.APPLICATION_JSON)
                        .content(objectMapper.writeValueAsString(request)))
                .andExpect(MockMvcResultMatchers.status().isOk())
                .andReturn();

        
        String responseBody = result.getResponse().getContentAsString();
        SearchResponse searchResponse = objectMapper.readValue(responseBody, SearchResponse.class);
  
        assertNotNull(searchResponse.getResults());
        assertFalse(searchResponse.getResults().getPatients().isEmpty());
    }
}

pom 版本

<dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>5.9.3</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>5.9.3</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-params</artifactId>
            <version>5.9.3</version>
            <scope>test</scope>
        </dependency>
        <!-- Mockito Core -->
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-core</artifactId>
            <version>5.3.1</version>
            <scope>test</scope>
        </dependency>
        <!-- Mockito JUnit Jupiter -->
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-junit-jupiter</artifactId>
            <version>5.3.1</version>
            <scope>test</scope>
        </dependency>

无法找出遗漏或错误的内容

我希望这些测试用例通过 mvn clean test 命令运行

java spring-boot mockito junit5 testcase
1个回答
0
投票

我相信您将一些不同的概念混合在一起,最终导致它不符合您的预期。让我将其分解为每个观察结果:

您将

MockitoExtension
WebMvcTest
AutoConfigureMockMvc
一起使用。
WebMvcTest
(取决于您的 Spring 版本)包括
AutoConfigureMockMvc
,因此您不需要包含它。此外,Spring 在内部为您做了很多事情,这使您不再需要直接使用
MockitoExtension
,所以我首先开始并删除该注释。

其次,在您的测试中,使用了

@InjectMocks
,但最终您只是直接调用该服务。看来您甚至没有在测试中使用
patientSearchController
,因此我将删除它,因为它只在
WebMvcTest
注释中的参考中需要。如果您稍后确实需要使用它,则如果您需要修改任何方法调用,则应使用
@Autowired
@SpyBean
对其进行注释。

第三,您当前的用例中不需要

@BeforeEach
设置方法,因为所有内容都应该通过
WebMvcTest
进行设置。另外
ObjectMapper
是由 Spring 提供的,所以除非你只想要一个全新的,否则你可以通过添加
@Autowired
注解来使用它。

第四,我没有看到

patientSearchService
连接在控制器代码中,因此您需要确保它可以通过
@Autowired
注释或通过将该字段作为最终字段的构造函数使用(如果您使用 Lombok,则
 @RequiredArgsConstructor
很有帮助)。

清理完上述内容后,您将获得成功的运行或指导您成功运行的新消息。

© www.soinside.com 2019 - 2024. All rights reserved.