Micronaut 1.1 - Improvements in JUnit Tests
Micronaut 1.1.0.RC2 is the latest version as of writing this post.
JUnit 5 is now the default test framework for Java projects.
Following are the dependencies from the service we created using Micronaut 1.0.5
dependencies {
annotationProcessor "io.micronaut:micronaut-inject-java"
annotationProcessor "io.micronaut:micronaut-validation"
compile "io.micronaut:micronaut-inject"
compile "io.micronaut:micronaut-validation"
compile "io.micronaut:micronaut-runtime"
compile "io.micronaut:micronaut-http-client"
compile "javax.annotation:javax.annotation-api"
compile "io.micronaut:micronaut-http-server-netty"
compileOnly "io.micronaut:micronaut-inject-java"
runtime "ch.qos.logback:logback-classic:1.2.3"
testCompile "junit:junit:4.12"
testCompile "io.micronaut:micronaut-inject-java"
testCompile "org.hamcrest:hamcrest-all:1.3"
}
A java service generated using Micronaut 1.1.0.RC2 includes the following dependencies.
dependencies {
annotationProcessor "io.micronaut:micronaut-inject-java"
annotationProcessor "io.micronaut:micronaut-validation"
compile "io.micronaut:micronaut-inject"
compile "io.micronaut:micronaut-validation"
compile "io.micronaut:micronaut-runtime"
compile "io.micronaut:micronaut-http-client"
compile "javax.annotation:javax.annotation-api"
compile "io.micronaut:micronaut-http-server-netty"
runtime "ch.qos.logback:logback-classic:1.2.3"
testAnnotationProcessor "io.micronaut:micronaut-inject-java"
testCompile "org.junit.jupiter:junit-jupiter-api"
testCompile "io.micronaut.test:micronaut-test-junit5"
testRuntime "org.junit.jupiter:junit-jupiter-engine"
}
We see that the JUnit 5 jupiter API is included with 'testCompile' scope and the jupiter engine is included with 'testRuntime' scope. Also there is 'micronaut-test-junit5' which includes the JUnit 5 extension class for Micronaut.
Now let's compare the tests generated by these two versions of Micronaut. Following is the controller test generated by the version 1.0.5.
package hello.service;
import io.micronaut.context.ApplicationContext;
import io.micronaut.http.HttpStatus;
import io.micronaut.http.client.RxHttpClient;
import io.micronaut.runtime.server.EmbeddedServer;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class HelloControllerTest {
@Test
public void testIndex() throws Exception {
try(EmbeddedServer server = ApplicationContext.run(EmbeddedServer.class)) {
try(RxHttpClient client = server.getApplicationContext().createBean(RxHttpClient.class, server.getURL())) {
assertEquals(HttpStatus.OK, client.toBlocking().exchange("/hello").status());
}
}
}
}
Below is the version of the code generated in Micronaut 1.1.0.RC2
package com.nareshak;
import io.micronaut.context.ApplicationContext;
import io.micronaut.http.HttpStatus;
import io.micronaut.http.client.RxHttpClient;
import io.micronaut.runtime.server.EmbeddedServer;
import io.micronaut.test.annotation.MicronautTest;
import org.junit.jupiter.api.Test;
import javax.inject.Inject;
import static org.junit.jupiter.api.Assertions.assertEquals;
@MicronautTest
public class HelloControllerTest {
@Inject
EmbeddedServer embeddedServer;
@Test
public void testIndex() throws Exception {
try(RxHttpClient client = embeddedServer.getApplicationContext().createBean(RxHttpClient.class, embeddedServer.getURL())) {
assertEquals(HttpStatus.OK, client.toBlocking().exchange("/hello").status());
}
}
}
The newer version looks less complex and feels much better. Isn't it?
In the prior versions, you had to take care of running the embedded server by invoking ApplicationContext.run(EmbeddedServer.class)
. Now all you have to do is annotate your class with @MicronautTest
and you will have an embedded server ready before your tests are run. If you end up with a NullPointerException
when you run your tests, chances are that you forgot to apply the @MicronautTest
annotation to your test class.
Here we obtain the ApplicationContext from the embeddedServer
using embeddedServer.getApplicationContext()
. Instead you could also create a field of type ApplicationContext
annotated with@Inject
. There is already an unused import of ApplicationContext which you could put into use!