Search code examples
javamicronautmicronaut-data

How to write integration tests for Micronaut APIs?


Let's say I have an API to GET list of users. Controller -> Service -> Repository. Coming from Spring background, where for writing test for this API, in test, we could declare the repository with @Autowired and insert the user data using this repository(in data setup part). Then make that API call and then assert the response. How to do this in Micronaut?


Solution

  • You can implement an integration test in a similar fashion in Micronaut using the official Micronaut Test module.

    Assuming you are using JUnit 5, here is a code sample from the Micronaut Test documentation page. (There are similar examples for Spock, KotlinTest, and Kotest, just in case you use a different testing framework.)

    package io.micronaut.test.junit5;
    
    import io.micronaut.test.extensions.junit5.annotation.MicronautTest;
    import org.junit.jupiter.api.Assertions;
    import org.junit.jupiter.params.ParameterizedTest;
    import org.junit.jupiter.params.provider.CsvSource;
    
    import javax.inject.Inject;
    
    @MicronautTest 
    class MathServiceTest {
    
        @Inject
        MathService mathService; 
    
        @ParameterizedTest
        @CsvSource({"2,8", "3,12"})
        void testComputeNumToSquare(Integer num, Integer square) {
            final Integer result = mathService.compute(num); 
    
            Assertions.assertEquals(
                    square,
                    result
            );
        }
    }
    

    The @MicronautTest annotation instructs the test runner to start up a Micronaut application for the test purpose. Then the @Inject annotation injects the MathService bean (similarly to the @Autowired annotation.) Now it's up to you to call the injected service to initialize the desired state before you run your assertions.

    Also, take a look at this test example from the official "Access a database with JPA and Hibernate" user guide. It shows how you can use the declarative HTTP client (the one injected as @Inject @Client("/") HttpClient client) to test your endpoints against the application started with the @MicronautTest annotation. You can benefit from both styles. For instance, you can inject service (or repository) and call it to prepare the desired initial state for the integration test, or you can do exactly that by calling specific endpoints (if they exist) that can create the data you want to retrieve from the controller with the real REST API call.

    UPDATE: As Sascha Frinken mentioned in the comment below, @MicronautTest wraps the test execution with the transaction by default. In this case, when you call repository.save(t) method inside the test method, it won't get committed until the transaction is completed. You can turn off this behavior with:

    @MicronautTest(transactional = false)