Posted at

Micronaut入門2〜ユニットテスト〜


概要

Micronaut入門1〜導入〜のつづき

前回作成したHelloControllerを少し拡張してユニットテストを行う。

Micronaut拡張モジュールのMicronaut Testを使用する。


Micronaut Testとは

Micronaut用のテストフレームワーク


  • JUnit 5

  • Spock

どちらかでテストを行うことができる。

今回はJUnit 5を使用してテストする。


実装クラスの修正・追加


コントローラーの修正

HelloControllerにテスト用のメソッドを追加する。


HelloController.java

import io.micronaut.http.MediaType;

import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import my.app.service.HelloService;

@Controller("/hello")
public class HelloController {
HelloService helloService;

HelloController(HelloService helloService) {
this.helloService = helloService;
}

@Get(produces = MediaType.TEXT_PLAIN)
public String index() {
return "hello world!!";
}

// 複数パラメータでのテスト用に追加
@Get(uri = "/{path}",processes = MediaType.TEXT_PLAIN)
public String index(String path) {
return path;
}

// サービスクラスの処理Mock確認のために追加
@Get(uri = "/compute/{number}",processes = MediaType.TEXT_PLAIN)
public String compute(Integer number) {
// テスト時にcomputeメソッドをMockにする。
return String.valueOf(helloService.compute(number));
}
}



サービスクラスの追加


HelloService

public interface HelloService {

public Integer compute(Integer num);
}


HelloServiceImpl

import javax.inject.Singleton;

@Singleton
public class HelloServiceImpl implements HelloService {
@Override
public Integer compute(Integer num) {
return num * 4;
}
}



ユニットテスト


依存ライブラリの追加


build.gradle

dependencies {

・・・
testAnnotationProcessor "io.micronaut:micronaut-inject-java"
testCompile "io.micronaut.test:micronaut-test-junit5"
testCompile "org.junit.jupiter:junit-jupiter-params"
testCompile "org.mockito:mockito-core:2.24.5"
testRuntime "org.junit.jupiter:junit-jupiter-engine"
}


ユニットテストの追加


HelloControllerTest.java

import io.micronaut.http.HttpRequest;

import io.micronaut.http.client.RxHttpClient;
import io.micronaut.http.client.annotation.Client;
import io.micronaut.test.annotation.MicronautTest;
import io.micronaut.test.annotation.MockBean;
import my.app.service.HelloService;
import my.app.service.HelloServiceImpl;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.junit.jupiter.params.provider.ValueSource;

import javax.inject.Inject;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.*;

@MicronautTest
public class HelloControllerTest {
// RxHttpClientでHelloControllerをテストする
@Inject
@Client("/")
RxHttpClient client;

@Inject
HelloService helloService;

@Test
void testHelloIndex() {
final String result = client.toBlocking().retrieve(HttpRequest.GET("/hello"), String.class);
assertEquals(
"hello world!!",
result
);
}

@ParameterizedTest
// パラメータを複数渡して同一ソースで複数回テストすることができる
@ValueSource(strings = { "racecar", "radar" })
void testHelloIndexPath(String path) {
final String result = client.toBlocking().retrieve(HttpRequest.GET("/hello/" + path), String.class);
assertEquals(
path,
result
);
}

@ParameterizedTest
@CsvSource({"2,4", "3,9"})
void testComputeNumToSquare(Integer num, Integer square) {

// Mockの振る舞いを設定する
when(helloService.compute(num))
.then(invocation -> Long.valueOf(Math.round(Math.pow(num, 2))).intValue());

// コントローラーを呼び出して結果を取得する
final Integer result = client.toBlocking().retrieve(HttpRequest.GET("/hello/compute/" + num), Integer.class);

assertEquals(
square,
result
);
verify(helloService).compute(num);
}

// MockBeanを使用してMock定義
@MockBean(HelloServiceImpl.class)
HelloService mathService() {
return mock(HelloService.class);
}
}



所感

JUnitをしようしてのユニットテストなので導入障壁は低そう。

Micronautの起動が早いので、テストも軽快でよかった。


参考

https://micronaut-projects.github.io/micronaut-test/latest/guide/index.html