【问题标题】:Why Getting Empty Response when writing UnitTest为什么在编写 UnitTest 时得到空响应
【发布时间】:2020-04-25 22:12:42
【问题描述】:

我正在学习为 SpringBoot Restcontroller 编写单元测试,写了这个并且测试通过了

@RunWith(SpringRunner.class)
@SpringBootTest(classes = {FhirApp.class, TestSecurityConfiguration.class})
@AutoConfigureMockMvc
public class ObservationControllerTest {

    private ObjectMapper objectMapper = new ObjectMapper();

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private ObservationService observationService;

    @Test
    public void createObservationResource() throws Exception {

        given(observationService.createObservation(ResourceStringProvider.observationsource()))
                .willReturn(responseDocument);

        String jsonString = objectMapper.writeValueAsString(
                          ResourceStringProvider.observationsource());

        mockMvc.perform(post("/Observation")
            .contentType(MediaType.APPLICATION_JSON)
            .content(jsonString))
            .andExpect(status()
            .isOk());
}

但是作为 thisthis ,我也得到了 response.getContentAsString() 的空响应:

Mockito.when(observationService.createObservation(Mockito.any())).thenReturn(responseDocument);

String jsonString = objectMapper.writeValueAsString(ResourceStringProvider.observationsource());

MockHttpServletResponse response = mockMvc.perform(post("/Observation")
            .contentType(MediaType.APPLICATION_JSON)
            .content(jsonString))
            .andReturn()
            .getResponse();

    assertThat(response.getContentAsString())
        .isEqualTo(new ObjectMapper()
                            .writeValueAsString(responseDocument));

我已经尝试过他们提供的解决方案:

1: Using Mockito.any(String.class) 
2: webEnvironment = SpringBootTest.WebEnvironment.MOCK
3: using thenCallRealMethod instead of thenReturn(responseDocument)

但不幸的是它没有用,已经尝试了不同的可能性,我也尝试过使用 MockitoJunitRunner :

@RunWith(MockitoJUnitRunner.class)
@SpringBootTest(classes = {FhirApp.class, TestSecurityConfiguration.class})
@AutoConfigureMockMvc
public class ObservationControllerTest {

private MockMvc mockMvc;

@Mock
private ObservationService observationService;

@Mock
private RequestFilter requestFilter;

@InjectMocks
private ObservationController observationController;

@Before
public void setup() {
    Resource resource = Utility.convertFromStringToFhirResource(Observation.class,ResourceStringProvider.observationResponse());
    responseDocument=Utility.convertFromFhirResourceToMongoInsertibleDoc(resource);

    //these line enabled for MockitoJUnitRunner only 
    this.mockMvc = MockMvcBuilders.standaloneSetup(observationController)
        .setControllerAdvice(new FhirRuntimeException("Error Happened"))
        .addFilters(requestFilter)
        .build();
}

@Test
public void createObservationResource()throws Exception{
    Mockito.when(observationService.createObservation(ResourceStringProvider.observationsource())).thenReturn(responseDocument);

    String jsonString = objectMapper.writeValueAsString(ResourceStringProvider.observationsource());
    MockHttpServletResponse response = mockMvc.perform(
        post("/Observation")
        .contentType(MediaType.APPLICATION_JSON)
        .content(jsonString))
        .andReturn()
        .getResponse();

    assertThat(response.getContentAsString()).isEqualTo(new ObjectMapper().writeValueAsString(responseDocument));
}

我认为由于没有多少人经历过这样的问题,所以没有太多谈论这个问题。响应状态正常时响应为空的原因是什么?

控制器代码:

@RestController
@RequestMapping("/api")
public class ObservationController {

    @Autowired
    private ObservationService observationService;


    @GetMapping("/Observation/{id}")
    public ResponseEntity<Document> getObservationByID(
        @RequestParam("_pretty") Optional<String> pretty,
        @PathVariable("id") String id) {
        Document resultDoc = observationService.getObservationById(id);
        return new ResponseEntity<>(resultDoc, HttpStatus.OK);
    }


    @PostMapping(path = "/Observation", consumes = {"application/json", "application/fhir+json"},
        produces = {"application/json", "application/fhir+json"})
    public ResponseEntity<Document> createObservationResource(@RequestBody String fhirResource) {
        Document fhirDoc = observationService.createObservation(fhirResource);
        return new ResponseEntity<>(fhirDoc,
            Utility.createHeaders(fhirDoc),
            HttpStatus.CREATED);
    }

    //other methods
}

我意识到在测试中发布的调用应该是 /api/Observation ,但它没有任何区别。提前致谢。

【问题讨论】:

  • 当你调试你的测试时,你发现了什么问题?如果您有一个空结果,那么您返回给客户端的任何内容都是空的。但是你还没有发布你的服务器端代码是什么样的,所以我们不知道。
  • 我已经更新了控制器的代码。实际上整个项目是使用 Jhipster 生成的 Spring-Boot 项目。
  • 什么时候调试你的测试?你能验证Document fhirDoc 不为空吗?
  • 这可能是因为ResourceStringProvider.observationsource() 创建了不同的对象,当您在模拟中使用它们时这些对象不匹配。你可以尝试重写equals方法。
  • 基于您的 cmets 我使用 Mockito.verify() 检查并且控制器本身没有以某种方式被调用。这颗宝石thepracticaldeveloper.com/2017/07/30/… 也帮了很多忙。

标签: java spring-boot spring-boot-test


【解决方案1】:

在此处发布完整的答案以及导入,以便对某人有所帮助(实际上我们不需要上面的任何注释,这是运行它的一种方式,在我的发现中,我遇到了这个post,这有助于解决设计如果您继续使用@InjectMocks 方法可能会出现问题)

import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;

import com.comitemd.emr.datalayer.fhir.service.ObservationService;
import com.comitemd.emr.datalayer.fhir.utility.ResourceStringProvider;
import com.comitemd.emr.datalayer.fhir.utility.Utility;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.bson.Document;
import org.hl7.fhir.r4.model.Observation;
import org.hl7.fhir.r4.model.Resource;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;

//@RunWith(MockitoJUnitRunner.class)
public class ObservationControllerStandaloneTest {

    private MockMvc mockMvc;
    @Mock
    private ObservationService observationService;
    @InjectMocks
    private ObservationController observationController;

    private Document responseDocument;
    @Before
    public void setup() {
       MockitoAnnotations.initMocks(this);// enable this or MockitoJUnitRunner.class
        Resource resource = Utility
            .convertFromStringToFhirResource(Observation.class, ResourceStringProvider.observationResponse());
         responseDocument=Utility.convertFromFhirResourceToMongoInsertibleDoc(resource);
        this.mockMvc = MockMvcBuilders.standaloneSetup(observationController).build();
    }

    @Test
    public void createObservationResource()throws Exception{
        Mockito.when(observationService.createObservation(ResourceStringProvider.observationsource()))
            .thenReturn(responseDocument);

        MockHttpServletResponse response = mockMvc.perform(
            post("/api/Observation")
                .contentType(MediaType.APPLICATION_JSON)
                .content(ResourceStringProvider.observationsource()))
            .andDo(MockMvcResultHandlers.print())
            .andReturn()
            .getResponse();

        verify(observationService, times(1)).createObservation(Mockito.any());
        assertThat(response.getContentAsString()).isEqualTo(new ObjectMapper().writeValueAsString(responseDocument));
    }
}

【讨论】:

  • 不确定为什么一个工作程序被否决了?
猜你喜欢
  • 2016-11-22
  • 1970-01-01
  • 2015-07-09
  • 1970-01-01
  • 2012-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-28
相关资源
最近更新 更多