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!