Injection into tests
So far we have only covered integration style tests that test the app via HTTP endpoints, but what if we want to do unit testing and test our beans directly?
Quarkus supports this by allowing you to inject CDI beans into your tests via the @Inject annotation (in fact, tests in Quarkus are full CDI beans, so you can use all CDI functionality). Let’s create a simple test that tests the greeting service directly without using HTTP.
-
Create a new test class file in
src/testin theorg.acme.peoplepackage calledGreetingServiceTest.java. Use the following code for the file’s contents (note we’ve included the proper imports for you):package org.acme.people; import jakarta.inject.Inject; import org.acme.people.service.GreetingService; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import io.quarkus.test.junit.QuarkusTest; @QuarkusTest public class GreetingServiceTest { private static final Logger LOGGER = LoggerFactory.getLogger("GreetingServiceTest"); @Inject // (1) GreetingService service; @Test public void testGreetingService() { Assertions.assertTrue(service.greeting("Quarkus").startsWith("hello Quarkus")); } }(1) Here we are injecting our
GreetingServiceand calling it, just as our RESTful resource endpoint does in the production code. -
You will see new test along with your existing tests run instantly in the terminal once again. Verify the tests are passing.
As mentioned above Quarkus tests are actually full CDI beans, and as such you can apply CDI interceptors as you would normally. As an example, if you want a test method to run within the context of a transaction you can simply apply the
@Transactionalannotation to the method and the transaction interceptor will handle it.In addition to this you can also create your own test stereotypes. Stereotypes can be particularly useful in large applications where you have a number of beans that perform similar functions, as it allows you to do something akin to multiple inheritance (multiple annotations) without having to repeat yourself over and over.
For example we could create a
@TransactionalQuarkusTestif we needed to write a large number of tests that required transactional support with particular configuration. It would look like (do not copy this code anywhere!)@QuarkusTest @Stereotype @Transactional @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface TransactionalQuarkusTest { }If we then apply this annotation to a test class it will act as if we had applied both the
@QuarkusTestand@Transactionalannotations, e.g.:@TransactionalQuarkusTest public class TestStereotypeTestCase { @Inject UserTransaction userTransaction; @Test public void testUserTransaction() throws Exception { Assertions.assertEquals(Status.STATUS_ACTIVE, userTransaction.getStatus()); } }