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?
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)
@MicronatTest
? If so then turn off transaction by setting @MicronatTest(transactional = false)
–
Chaing Seems we don't have a piece of code that can help us to tell you where your problem could be it's a little bit complicated to give a solid solution, even tho I think this could help you.
Every time you run your test on a micronaut app you will have available on your context the services and repositories, if you want to test that your controller > service communicates correctly you can create a @Client
I'll give you an example of a test with Spock Framework
class PersonControllerSpec extends Specification {
@Shared @AutoCleanup EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer)
@Shared PersonClient client
@Shared PersonService service
void setupSpec(){
client = embeddedServer.applicationContext.getBean(PersonClient)
service = embeddedServer.applicationContext.getBean(PersonService)
}
@Transactional
void cleanup(){
Person.list()*.delete()
}
def "/people should return 2 elements" (){
given:
service.save(new Person(name: "Daniel", lastName: "Araiza", age: 22, phone: "235-547-8761" ))
service.save(new Person(name: "Omar", lastName: "Bautista", age: 32, phone: "765-234-8623"))
when:
List<Person> people = client.list()
then:
people.size() == 2
}
}
You can see more examples on my repository a link!
© 2022 - 2024 — McMap. All rights reserved.