2

I've created a test to try out my microservice. A simple get call that through 3 parameters returns me the message with the specifications of that user. I created it using Junit and Mockito. Below:

@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);
});

clearly the constants of the variables that are passed conform to those of the message that must return me. When I try to start the test it gives me an error This is the stacktrace I am reporting:

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
 ;

Trying to go to Debug, I get this error back, but I don't know how to handle it at all

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

I guess the two errors are related but I don't know how to fix this.

EDIT: As requested, I add my Car Service:

@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;
    }
}

and my 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
    }
Numero 21
  • 144
  • 9
  • Most likely the endpoint has required parameters (name, plate, price) but you provided none in your request. Please show us the method under test in the controller. – Lesiak Mar 29 '21 at 12:53
  • Why are you sending parameters to get request in a RequestBody? Although this is not the source of the problem (missing body in the request is) I would advise reconsidering the signature of this method before writing a test to cast this behaviour in cement. – Lesiak Mar 31 '21 at 17:46
  • Is this a `mockMvc` test? . It looks like to me, then it may not load your service classes, it only loads the slice of `controller` class in context. How are you mocking your service class in test? – code_mechanic Apr 05 '21 at 06:06
  • Please add complete test class how it looks. – code_mechanic Apr 06 '21 at 03:15

2 Answers2

4

First of all, using GET requests with a body is the poor practice. Use POST requests instead.

Then, spring tells you about org.springframework.web.HttpMediaTypeNotSupportedException and in your controller method getCars() you describe the next:

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

But in your test you don't specify any content-type:

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

Try to add content-type .contentType(MediaType.APPLICATION_JSON):

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

Also, I don't see how you pass the body to the request. Try to add it .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));

where mapper is ObjectMapper. I assume you are using com.fasterxml.jackson.databind.ObjectMapper.

Volodya Lombrozo
  • 834
  • 4
  • 15
0

You need to do the argument matching properly. You probably want to test, whether or not the parameters are equal to, and not if they are the same as the parameters you defined in your test class. Try this:

Mockito.when(service.getByPlate(Mockito.eq(carsRequest.getName()), Mockito.eq(carsRequest.getPlate()), Mockito.eq(carsRequest.getPrice()))).thenReturn(cars);
Mario Varchmin
  • 1,159
  • 8
  • 17
  • Hi, I tried your solution but it doesn't work, it gives me the same error. – Numero 21 Mar 29 '21 at 13:33
  • Sorry to hear that. You could also try with Mockito.any() instead of Mockito.eq(...) to narrow the cause of the problem. – Mario Varchmin Mar 29 '21 at 13:36
  • Nothing to do, the exact same mistake – Numero 21 Mar 29 '21 at 13:47
  • Your endpoint seems to be access protected (judging from the "SpringSecurityLdapTemplate - Ignoring PartialResultException" message). Can you remove the access protection and test again? Have you ever tried to run your test in the debugger? – Mario Varchmin Mar 29 '21 at 14:16
  • I did both, but the problem remains – Numero 21 Mar 29 '21 at 14:36
  • When you run your code in the debugger, you are able to step into the body of th getCars() method of your CarController (or set a breakpoint there)? – Mario Varchmin Mar 29 '21 at 14:40
  • I set a breakpoint in the controller, but it didn't give me any problems, i.e. the error persists but did not detect anything in the breakpoint part – Numero 21 Mar 29 '21 at 14:48
  • What does "didn't give me any problems mean"? Did the code execution reach the breakpoint (i.e. did the code stop there)? – Mario Varchmin Mar 29 '21 at 14:51
  • it didn't stop there – Numero 21 Mar 29 '21 at 15:55
  • Then the code in your controller code didn't get executed. This means, the problem is not related to Mockito mocking. It is probably related to the security/authentication setup of your application. – Mario Varchmin Mar 29 '21 at 16:01
  • But it doesn't report an authentication or security-related error, the exception it throws in debug appears to be related to Mockito – Numero 21 Mar 29 '21 at 16:15