Junit 测试中的模拟错误 UnfinishedStubbingException

Mock error UnfinishedStubbingException in a Junit test

我创建了一个测试来试用我的微服务。一个简单的 get 调用,通过 3 个参数 return 向我发送包含该用户规格的消息。我使用 Junit 和 Mockito 创建了它。以下:

@Test
public void TestOk() throws Exception{
    CarsRequest carsRequest = new CarsRequest();
    carsRequest.setName(TestCostants.NAME);
    carsRequest.setPlate(TestCostants.PLATE);
    carsRequest.setPrice(TestCostants.PRICE);
    Cars car = new Cars("BMW","TG35647", "15000","re",80000000,
            null,null);
    List<Cars> cars = new ArrayList<>();
    cars.add(car);


    Mockito.when(
            service.getByPlate(carsRequest.getName(), carsRequest.getPlate(),
                    carsRequest.getPrice())).thenReturn(cars);
    RequestBuilder requestBuilder = MockMvcRequestBuilders.get(
            "/resources/cars").accept(
            MediaType.APPLICATION_JSON).header("Authorization","Basic //myAuth");
    MvcResult result = mockMvc.perform(requestBuilder).andReturn();
    System.out.println(result.getResponse());


    String expected = "{\"name\"=\"BMW\", \"plate\"=\"TG35647\", " +
            "\"price\"=\"15000\",\"brand\"=\"re\", \"kilometers\"=\"80000000\", \"revisiondate\"=\"null\", \"owner\"=\"null\"}";
    JSONAssert.assertEquals(expected, result.getResponse()
            .getContentAsString(), false);
});

显然,传递的变量常量与必须 return 我的消息的常量一致。当我尝试开始测试时,它给我一个错误 这是我报告的堆栈跟踪:

2021-03-29 12:45:07.906 [main] INFO  o.s.s.l.SpringSecurityLdapTemplate - Ignoring PartialResultException
{
  "@timestamp" : "2021-03-29T12:45:08.119+02:00",
  "@version" : "1",
  "message" : "[GET] http://localhost/resources/cars/ call resulted in the following error: Content type '' not supported",
  "logger_name" : "my.project.car.controller.ExceptionHandlingController",
  "thread_name" : "main",
  "level" : "ERROR",
  "level_value" : 40000
}
ErrorResponse: org.springframework.web.HttpMediaTypeNotSupportedException: Content type '' not supported
org.springframework.mock.web.MockHttpServletResponse@135f160e
MockHttpServletRequest:
      HTTP Method = GET
      Request URI = /resources/cars/
       Parameters = {}
          Headers = [Accept:"application/json", Authorization:"Basic //myAuth"]
             Body = null
    Session Attrs = {}
Handler:
             Type = null
Async:
    Async started = false
     Async result = null
Resolved Exception:
             Type = org.springframework.web.HttpMediaTypeNotSupportedException
ModelAndView:
        View name = null
             View = null
            Model = null
FlashMap:
       Attributes = null
MockHttpServletResponse:
           Status = 500
    Error message = null
          Headers = [Content-Type:"application/json", X-Content-Type-Options:"nosniff", X-XSS-Protection:"1; mode=block", Cache-Control:"no-cache, no-store, max-age=0, must-revalidate", Pragma:"no-cache", Expires:"0", X-Frame-Options:"DENY"]
     Content type = application/json
             Body = {"esito":"KO","codiceEsito":"ERROR","descrizioneEsito":"Errore generico"}
    Forwarded URL = null
   Redirected URL = null
          Cookies = []
java.lang.AssertionError:
Expected: name
     but none found
 ;
Expected: plate
     but none found
 ;
Expected: price
     but none found
 ;
Expected: brand
     but none found
 ;
Expected: kilometers
     but none found
 ;
Expected: revisiondate
     but none found
 ;
Expected: owner
     but none found
 ;

试图去调试,我得到了这个错误,但我完全不知道如何处理它

Method threw 'org.mockito.exceptions.misusing.UnfinishedStubbingException' exception. Cannot evaluate my.project.service.CarService$MockitoMock24138024.toString()

我想这两个错误是相关的,但我不知道如何解决这个问题。

编辑: 根据要求,我添加我的汽车服务:

@Service
public class CarService {
    @Autowired
    CarRepository carRepository;
    @Autowired
    ObjectMapper objectMapper;

    public List<Car> getByPlate(String name, String plate, String price) throws JsonProcessingException {
        List<Car> car = new ArrayList<>();
        for (Cache.Entry<String, Car> entry: carRepository.findAllByNameAndPlateAndPrice(name, plate,price)){
            car.add(new Car(entry.getKey(), entry.getValue()));
            System.out.println("Entry: " + objectMapper.writeValueAsString(entry));
        }
        return cars;
    }
}

和我的 CarController

@RestController
@RequestMapping("/resources/")
public class CarController {
    @Autowired
    CarService carService;
    @Autowired
    ObjectMapper objectMapper;
    @GetMapping(
    value = "/cars",
    consumes = {MediaType.APPLICATION_JSON_VALUE},
    produces = {MediaType.APPLICATION_JSON_VALUE})
    public CarsResponse getCars(@RequestBody CarsRequest request) throws IOException {
        //some code
    }

首先,使用GET请求的正文是poor practice。请改用 POST 个请求。

然后,spring 告诉你关于 org.springframework.web.HttpMediaTypeNotSupportedException 并且在你的控制器方法中 getCars() 你描述下一个:

    consumes = {MediaType.APPLICATION_JSON_VALUE},
    produces = {MediaType.APPLICATION_JSON_VALUE}

但是在你的测试中你没有指定任何内容类型:

RequestBuilder requestBuilder = MockMvcRequestBuilders.get(
        "/resources/cars").accept(
        MediaType.APPLICATION_JSON).header("Authorization","Basic //myAuth");

尝试添加内容类型.contentType(MediaType.APPLICATION_JSON):

 RequestBuilder requestBuilder = MockMvcRequestBuilders.get("/resources/cars")
                .accept(MediaType.APPLICATION_JSON)
                .contentType(MediaType.APPLICATION_JSON)
                .header("Authorization", "Basic //myAuth");

此外,我看不出您是如何将正文传递给请求的。尝试添加它 .content(mapper.writeValueAsString(carsRequest)):

 RequestBuilder requestBuilder = MockMvcRequestBuilders.get("/resources/cars")
                .accept(MediaType.APPLICATION_JSON)
                .contentType(MediaType.APPLICATION_JSON)
                .header("Authorization", "Basic //myAuth")
                .content(mapper.writeValueAsString(carsRequest));

其中 mapperObjectMapper。我假设您使用的是 com.fasterxml.jackson.databind.ObjectMapper.