org.springframework.web.client.HttpClientErrorException: 400 null

14,291

You should use TestRestTemplate instead of RestTemplate.

Class TestRestTemplate

Convenient alternative of RestTemplate that is suitable for integration tests. They are fault tolerant, and optionally can carry Basic authentication headers. If Apache Http Client 4.3.2 or better is available (recommended) it will be used as the client, and by default configured to ignore cookies and redirects.

Change

@Test
public void checkFilterDataControllerInvalidBodyResponse() {
    String servicePath = getBaseUrl() + "/statistics/filters?startDate={startDate}&endDate={endDate}";
    RestTemplate restTemplate = new RestTemplate();
    ResponseEntity<String> response = restTemplate.getForEntity(servicePath, String.class, "", "");
    assertThat(response, notNullValue());
    assertThat(response.getStatusCode(), equalTo(HttpStatus.BAD_REQUEST));
}

To

@Test
public void checkFilterDataControllerInvalidBodyResponse() {
    String servicePath = getBaseUrl() + "/statistics/filters?startDate={startDate}&endDate={endDate}";
    TestRestTemplate restTemplate = new RestTemplate();
    ResponseEntity<String> response = restTemplate.getForEntity(servicePath, String.class, "", "");
    assertThat(response, notNullValue());
    assertThat(response.getStatusCode(), equalTo(HttpStatus.BAD_REQUEST));
}
Share:
14,291
Woland
Author by

Woland

I am a back-end software engineer with a passion for architecture and design. Have experience mostly in the java ecosystem, but I'm not limited by that.

Updated on June 04, 2022

Comments

  • Woland
    Woland almost 2 years

    I wrote test for FilterDataController. But I have the following error during execution test. When I send manually GET request I receive correct JSON.

    org.springframework.web.client.HttpClientErrorException: 400 null
    
        at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:91)
        at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:667)
        at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:620)
        at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:580)
        at org.springframework.web.client.RestTemplate.getForEntity(RestTemplate.java:312)
        at com.company.integration.tests.rest.StatisticEndpointTest.checkFilterDataControllerInvalidBodyResponse(StatisticEndpointTest.java:284)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
        at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
        at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
        at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
        at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
        at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
        at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
        at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
        at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
        at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
        at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
        at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
        at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
        at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
        at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
        at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
        at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
        at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
        at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
        at org.junit.runners.Suite.runChild(Suite.java:128)
        at org.junit.runners.Suite.runChild(Suite.java:27)
        at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
        at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
        at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
        at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
        at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
        at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
        at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
        at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:117)
        at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
        at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:262)
        at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:84)
    

    My test:

    @Test
    public void checkFilterDataControllerInvalidBodyResponse() {
        String servicePath = getBaseUrl() + "/statistics/filters?startDate={startDate}&endDate={endDate}";
        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<String> response = restTemplate.getForEntity(servicePath, String.class, "", "");
        assertThat(response, notNullValue());
        assertThat(response.getStatusCode(), equalTo(HttpStatus.BAD_REQUEST));
    }
    

    FilterDataController

    /**
     * controller which provides possible filters data for UI
     */
    
    @RestController
    @RequestMapping("/statistics")
    @Api(value = "/statistics",description = "API for possible filters data")
    public class FilterDataController {
    
        public static final String DATE_FORMAT = "yyyy-MM-dd";
    
        @Autowired
        private FilterDataProvider filterDataProvider;
    
        @ApiOperation(value = "Get possible filter data",response = ResponseEntity.class)
        @ApiResponses(value = {
                @ApiResponse(code = 200, message = "The response data should be used as bricks in all future statistics requests"),
                @ApiResponse(code = 204, message = "Data not found. Select another timeframe")})
        @RequestMapping(path = "/filters", method = RequestMethod.GET)
        public ResponseEntity<Object> getPossibleFilterData(
                @RequestParam(value = "startDate") @DateTimeFormat(pattern=DATE_FORMAT) final Date startDate,
                @RequestParam(value = "endDate") @DateTimeFormat(pattern=DATE_FORMAT) final Date endDate) {
            if (startDate == null || endDate == null){
                 throw new ValueNotAllowedException("Dates mustn't be null");
            }
            if (endDate.compareTo(startDate) == -1){
                throw new ValueNotAllowedException("End date should be after or equal start date");
            }
            else {
                Date newEndDate = endDate;
                if (startDate.equals(endDate)){
                    newEndDate = new Date(endDate.getTime() + TimeUnit.DAYS.toMillis(1) - 1);
                }
                List<String> possibleMails =  Lists.newArrayList(filterDataProvider.getPossibleMails(startDate, newEndDate));
    
                <...>
    
                return new ResponseEntity<>(new FilterResponse(possibleMails, possibleSubjects, possibleCountries, possibleSizes, possibleStates),HttpStatus.OK);
            }
        }
    
        @ExceptionHandler(ValueNotAllowedException.class)
        void handleBadRequests(HttpServletResponse response, ValueNotAllowedException ex) throws IOException {
            response.sendError(HttpStatus.BAD_REQUEST.value(), ex.getMessage());
        }
    }
    

    Response from Postman:

    GET http://localhost:8888/statistics/filters?startDate=&endDate=

    {
      "timestamp": 1476690591750,
      "status": 400,
      "error": "Bad Request",
      "exception": "com.services.exceptions.ValueNotAllowedException",
      "message": "Dates mustn't be null",
      "path": "/statistics/filters"
    }
    

    Params that I send to getForEntity is correct, because when I send the same params but with correct dates - it's works good.

    • Fernando Sanchiz
      Fernando Sanchiz over 7 years
      You can catch this as Object better: ResponseEntity<Object[]> responseEntity = restTemplate.getForEntity(urlGETList, Object[].class); for control it
    • Woland
      Woland over 7 years
      @FernandoSanchiz ok, what can you say about the topic question?