Search code examples
spring-bootjunitopenapi-generatorspringdoc-openapi-uijunit-jupiter

Unit Testing Spring Boot API RESTful endpoints generated by Open API 3 YAML files


I have an application that is using Spring Boot (latest version) and creating a back-end that has RESTful api's. Traditionally, I have created controllers like:

@RestController
@RequestMapping("/contacts")
public class ContactController {
    @Autowired
    private ContactService service;

        @RequestMapping(value = "/contactId/{contactId}", 
         method = RequestMethod.GET, headers = "Accept=application/json")
public @ResponseBody ContactEntity getContactById(@PathVariable("contactId") long contactId) {
    ContactEntity contactEntity = service.getContactById(contactId);
    return contactEntity;
}

And an integrated test has always been like:

@ExtendWith(SpringExtension.class)
@SpringBootTest(classes = ServiceContextConfiguration.class)
@ComponentScan("com.tomholmes.springboot.phonebook.server")
@Transactional
@WebAppConfiguration    
public class ContactControllerTest {
    @Test
    public void testGetContactById() throws Exception {
        MockHttpServletRequestBuilder requestBuilder = 
            MockMvcRequestBuilders.get(BASE_URL + "/contactId/6");           
        this.mockMvc.perform(requestBuilder)
            .andDo(print())
            .andExpect(status().isOk());
       }
}

This has always worked normally for years as a 'code first' api. Now, I am dealing with a contract-first API using OpenAPI 3 and a YAML file. The API is generated in the same location as before, and I would expect the test to work as it did before, but it does not.

So one resource:
[https://www.hascode.com/2018/08/testing-openapi-swagger-schema-compliance-with-java-junit-and-assertj-swagger/#API_Test] is suggesting I use the assertj-swagger for the OpenAPI / Swagger contract testing.

Is this the only way to go? Is there no way for me to use my old traditional testing which I find extremely useful as an integrated test.

There is a third method I am also looking into: [https://www.testcontainers.org/modules/mockserver/] Which I am going to try also, and I am sure it will work.

I'm also wondering if there is code out there to auto-generate the Test just like there is to generate the API endpoint and the model, it would make sense if the Open API 3 also had the ability to generate the test was well.

Ultimately, I'd like to use my old way of testing if I could, but if not, then I'll try the other ways.


Solution

  • We had the same issue after switching to open api contract first with auto-generated controllers/delegate interfaces. The fix was to import the delegate impl in addition to the controller itself. Example:

    @WebMvcTest(FeatureController.class)
    @Import(FeatureDelegateImpl.class)
    public class FeatureContractTest {
    
      @Autowired
      private MockMvc mvc;
    
      @MockBean
      private BusinessService businessService;
    ...
    

    FeatureController is the controller generated by open-api, which typically will be in a generated-sources folder within target. FeatureDelegateImpl is our own implementation of the delegate interface, which lives in the src/main folder.