spring-cloud / spring-cloud-contract

Support for Consumer Driven Contracts in Spring
https://cloud.spring.io/spring-cloud-contract
Apache License 2.0
720 stars 438 forks source link

Global Exception Handler not working while using Contract #558

Closed pjosalgado closed 6 years ago

pjosalgado commented 6 years ago

I'm currently using a Global Exception Handler on my REST microservice that designs the return of all my customized exceptions been throw on the project. Here is an example:

@ControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {

    @ExceptionHandler(value = WebServiceException.class)
    public ResponseEntity<ResponseError> handleWebServiceException(WebServiceException e) {
        return ResponseEntity.status(e.getStatus()).body(e.getError());
    }

}

In my code when a error occurs I simply throw a WebServiceException (with none try/catch written on the path return of the service) and my Exception Handler gets the exception and formats the return.

I started using Spring Cloud Contract (version 1.2.3.RELEASE).

The Contracts for test success calls (2xx like) are working perfectly, but the ones for error (4xx like, thrown by the WebServiceException) are not. When I wanna test a error process usually a exception is thrown by the service, wich in my case using a Exception Handler is OK on a normal call, but when testing with a Contract gives me a direct error message (saying that an exception was throw), as if the Exception Handler is not getting the error and returning the call.

Can somebody tell me if Contract does not work with Exception Handler of if I need to do some additional configuration?

marcingrzejszczak commented 6 years ago

Have you set up the context properly? Meaning, if you set up mock mvc you have to add all filters by yourself or reuse the web context. Example here https://github.com/rest-assured/rest-assured/wiki/Usage#using-spring-security-test . That way all filters will be setup for you.

pjosalgado commented 6 years ago

Here is what I have:

@ActiveProfiles("test")
@Profile("test")
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public abstract class BaseApplicationTests {

    @Autowired
    protected WebApplicationContext context;

    public void setup() {
        RestAssuredMockMvc.webAppContextSetup(this.context);
    }

}
public class ControllerTests extends BaseApplicationTests {

    @Autowired
    private SomeController controller;

    @Before
    public void setup() {
        super.setup();
        RestAssuredMockMvc.standaloneSetup(this.controller);
    }

}

I read your reference but did not understand how to add the Exception Handler in my configuration. Could you be more specific?

marcingrzejszczak commented 6 years ago
@ActiveProfiles("test")
@Profile("test")
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public abstract class BaseApplicationTests {

    @Autowired
    protected WebApplicationContext context;

       @Before
    public void setup() {
        RestAssuredMockMvc.webAppContextSetup(this.context);
    }

}

this should be your base class. Why do you set first the webAppContextSetup and then (most likely) override it with standaloneSetup ?

pjosalgado commented 6 years ago

It completely makes sense. Probably during the Contract configuration I followed the instructions not considering my current structure. Removing the standaloneSetup and using only webAppContextSetup solved my problem. Thank you, @marcingrzejszczak.

This ticket can be closed.

marcingrzejszczak commented 6 years ago

Glad that we solved it!

sparkmuse commented 6 years ago

Thank for the help. I have been working on this the whole morning :)

devdeegaw commented 5 years ago

You can create standaloneSetup with global exception handler like

RestAssuredMockMvc.standaloneSetup(this.controller, new GlobalExceptionHandler());