2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ユニットテスト環境にJUnit5とWireMockを使ったプロジェクトのひな型のメモ

Posted at

概要

この記事は、ユニットテスト環境にJUnit5とMockサーバにWireMockを使ったプロジェクトのひな型を作った時のメモです。

環境

  • Windows 10 Professional
  • OpenJDK 11
  • JUnit5 5.3.2
  • WireMock 2.20.0
  • Maven 3.6.0
  • Eclipse 2018-09

参考

JDK 11

> java -version
openjdk version "11.0.1" 2018-10-16
OpenJDK Runtime Environment 18.9 (build 11.0.1+13)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.1+13, mixed mode)

Maven

[Release Notes – Maven – Version 3.6.0] (https://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12316922&version=12338966)

D:\dev\apache-maven-3.6.0> bin\mvn.cmd -v
Apache Maven 3.6.0 (97c98ec64a1fdfee7767ce5ffb20918da4f719f3; 2018-10-25T03:41:47+09:00)
Maven home: D:\dev\apache-maven-3.6.0\bin\..
Java version: 11.0.1, vendor: Oracle Corporation, runtime: D:\openjdk\openjdk-11.0.1_windows-x64
Default locale: ja_JP, platform encoding: MS932
OS name: "windows 10", version: "10.0", arch: "amd64", family: "windows"

pom.xml

最終的なpom.xmlの内容を掲載します。

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.example</groupId>
  <artifactId>wiremock-demo</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>wiremock-demo</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>11</java.version>
    <!-- compiler -->
    <maven.compiler.source>${java.version}</maven.compiler.source>
    <maven.compiler.target>${java.version}</maven.compiler.target>
    <maven.compiler.showDeprecation>true</maven.compiler.showDeprecation>
    <maven.compiler.showWarnings>true</maven.compiler.showWarnings>
    <maven.compiler.verbose>true</maven.compiler.verbose>
    <!-- JUnit5 -->
    <junit.jupiter.version>5.3.2</junit.jupiter.version>
    <junit.platform.version>1.3.2</junit.platform.version>
    <!-- WireMock -->
    <wiremock.version>2.20.0</wiremock.version>
    <!-- REST Assured -->
    <rest-assured.version>3.2.0</rest-assured.version>
  </properties>

  <dependencies>
    <!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-engine -->
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-engine</artifactId>
      <version>${junit.jupiter.version}</version>
      <scope>test</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.junit.platform/junit-platform-launcher -->
    <dependency>
      <groupId>org.junit.platform</groupId>
      <artifactId>junit-platform-launcher</artifactId>
      <version>${junit.platform.version}</version>
      <scope>test</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/com.github.tomakehurst/wiremock -->
    <dependency>
      <groupId>com.github.tomakehurst</groupId>
      <artifactId>wiremock</artifactId>
      <version>2.20.0</version>
      <scope>test</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/io.rest-assured/rest-assured -->
    <dependency>
      <groupId>io.rest-assured</groupId>
      <artifactId>rest-assured</artifactId>
      <version>${rest-assured.version}</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <finalName>demo</finalName>
    <plugins>
      <!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-clean-plugin -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-clean-plugin</artifactId>
        <version>3.1.0</version>
      </plugin>
      <!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-compiler-plugin -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.0</version>
        <configuration>
          <compilerArgs>
            <arg>-Xlint:all</arg>
          </compilerArgs>
          <release>${java.version}</release>
        </configuration>
      </plugin>
      <!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-resources-plugin -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-resources-plugin</artifactId>
        <version>3.1.0</version>
      </plugin>
      <!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-jar-plugin -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <version>3.1.1</version>
      </plugin>
      <!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-surefire-plugin -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>3.0.0-M3</version>
        <!-- <configuration> <forkCount>0</forkCount> </configuration> -->
      </plugin>
      <!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-failsafe-plugin -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-failsafe-plugin</artifactId>
        <version>3.0.0-M3</version>
      </plugin>
    </plugins>
  </build>

</project>

JUnit5

[junit-jupiter-engine] (https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-engine)

<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-engine -->
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-engine</artifactId>
    <version>5.3.2</version>
    <scope>test</scope>
</dependency>

[junit-platform-launcher] (https://mvnrepository.com/artifact/org.junit.platform/junit-platform-launcher)

<!-- https://mvnrepository.com/artifact/org.junit.platform/junit-platform-launcher -->
<dependency>
    <groupId>org.junit.platform</groupId>
    <artifactId>junit-platform-launcher</artifactId>
    <version>1.3.2</version>
    <scope>test</scope>
</dependency>

[WireMock] (http://wiremock.org/)

[wiremock] (https://mvnrepository.com/artifact/com.github.tomakehurst/wiremock)

<!-- https://mvnrepository.com/artifact/com.github.tomakehurst/wiremock -->
<dependency>
    <groupId>com.github.tomakehurst</groupId>
    <artifactId>wiremock</artifactId>
    <version>2.20.0</version>
    <type>pom</type>
    <scope>test</scope>
</dependency>

[wiremock-junit5] (https://mvnrepository.com/artifact/ru.lanwen.wiremock/wiremock-junit5)

今回は使いませんでしたが、Third partyのJUnit5拡張機能もあります。

<!-- https://mvnrepository.com/artifact/ru.lanwen.wiremock/wiremock-junit5 -->
<dependency>
    <groupId>ru.lanwen.wiremock</groupId>
    <artifactId>wiremock-junit5</artifactId>
    <version>1.3.0</version>
    <scope>test</scope>
</dependency>

[REST Assured] (http://rest-assured.io/)

WireMockのスタブの動作確認用にREST Assuredを使用しました。

[rest-assured] (https://mvnrepository.com/artifact/io.rest-assured/rest-assured)

<!-- https://mvnrepository.com/artifact/io.rest-assured/rest-assured -->
<dependency>
    <groupId>io.rest-assured</groupId>
    <artifactId>rest-assured</artifactId>
    <version>3.2.0</version>
    <scope>test</scope>
</dependency>

WireMockの基本的な使い方

WireMockServer

現時点(2019/01)でJUnit5の拡張機能は用意されていないので、[Java (Non-JUnit) Usage] (http://wiremock.org/docs/java-usage/)を参考に、WireMockサーバをプログラム的(programmatically)に起動、停止させます。

@DisplayName("WireMock Test Demo")
public class WireMockDemoTests {

  private WireMockServer server;
  private RestAssuredConfig config;

  @BeforeEach
  void setup() {
    // REST Assured configuration
    config = config().encoderConfig(encoderConfig().appendDefaultContentCharsetToContentTypeIfUndefined(false))
                     .logConfig(logConfig().enablePrettyPrinting(true));

    server = new WireMockServer();
    server.start();
  }

  @AfterEach
  void tearDown() {
    server.stop();
  }

}

[Configuration] (http://wiremock.org/docs/configuration/)

import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
// ConsoleNotifier
Notifier notifier = new ConsoleNotifier(true);
// Slf4jNotifier
// Notifier notifier = new Slf4jNotifier(true);

Options options = options().port(8080).notifier(notifier);
server = new WireMockServer(options);

[Stubbing] (http://wiremock.org/docs/stubbing/)

スタブの登録方法

基本的なスタブの登録

import static com.github.tomakehurst.wiremock.client.WireMock.get;
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor;
@Test
@DisplayName("wiremock demo #1")
void mockDemo1() {

	// stub (WireMock)
	server.stubFor(get(urlEqualTo("/mock/demo/1")).withName("mock_demo_1")
			.willReturn(
					aResponse()
						.withStatus(200)
						.withHeader("Content-Type", "text/plain")
						.withBody("Hello world!"))
			);

	// exercise and assert (REST Assured)
	given()
		.config(config)
		.header("Content-Type", "text/plain")
		.when()
			.get("http://localhost:8080/mock/demo/1")
		.then()
			.assertThat()
				.contentType(ContentType.TEXT)
				.statusCode(200)
				.header("Matched-Stub-Name", "mock_demo_1")
				.body(Matchers.containsString("Hello world!"));

	// verify (WireMock)
	server.verify(getRequestedFor(urlEqualTo("/mock/demo/1"))
	        .withHeader("Content-Type", equalTo("text/plain")));
}

マッピングファイルを使う

デフォルトではsrc/test/resources/mappingsディレクトリ下に配置するマッピングファイル(拡張子がjson)からスタブのマッピングが登録されます。

マッピングファイルの例

requestとresponseにスタブの振る舞いを記述します。
nameはオプションですが明記しておくとMatched-Stub-Nameというレスポンスヘッダーにnameがセットされるようになります。

demo2.json
{
	"name": "mock_demo_2",
	"request": {
		"method": "GET",
		"url": "/mock/demo/2",
		"headers": {
			"Content-Type": {
				"matches": "application/json"
			}
		}
	},
	"response": {
		"status": 200,
		"body": "{\"name\": \"John\"}",
		"headers": {
			"Content-Type": "application/json"
		}
	}
}

マッピングファイルを利用することで、テストにスタブの設定コードを記述しなくても済むようになります。

@Test
@DisplayName("wiremock demo #2")
void mockDemo2() {

	// exercise and assert (REST Assured)
	given()
		.config(config)
		.header("Content-Type", "application/json")
		.when()
			.get("http://localhost:8080/mock/demo/2")
		.then()
			.assertThat()
				.contentType(ContentType.JSON)
				.statusCode(200)
				.header("Matched-Stub-Name", "mock_demo_2")
				.body("name", Matchers.equalTo("John"));

	// verify (WireMock)
	server.verify(getRequestedFor(urlEqualTo("/mock/demo/2"))
	        .withHeader("Content-Type", equalTo("application/json")));
}

Response Bodyに外部ファイルを利用する

Response Bodyの内容に外部ファイルを利用したい場合、bodyの代わりにbodyFileNameにファイル名を指定します。

demo3.json
{
	"name": "mock_demo_3",
	"request": {
		"method": "GET",
		"url": "/mock/demo/3",
		"headers": {
			"Content-Type": {
				"matches": "application/json"
			}
		}
	},
	"response": {
		"status": 200,
		"bodyFileName": "loto.json",
		"headers": {
			"Content-Type": "application/json"
		}
	}
}

デフォルトのファイルの設置場所はsrc/test/resources/__filesになります。

loto.json
{
	"lotto": {
		"lottoId": 5,
		"winning-numbers": [
			2,
			45,
			34,
			23,
			7,
			5,
			3
		],
		"winners": [
			{
				"winnerId": 23,
				"numbers": [
					2,
					45,
					34,
					23,
					3,
					5
				]
			},
			{
				"winnerId": 54,
				"numbers": [
					52,
					3,
					12,
					11,
					18,
					22
				]
			}
		]
	}
}
2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?