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

# 概要

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

**環境**

* Windows 10 Professional
* OpenJDK 11
* JUnit5 5.3.2
* AssertJ 3.11.1
* Mockito 2.23.4
* Maven 3.6.0
* Eclipse 2018-09

**参考**

* JUnit5
    * [JUnit 5 User Guide] (https://junit.org/junit5/docs/current/user-guide/)
    * [Third party Extensions] (https://github.com/junit-team/junit5/wiki/Third-party-Extensions)
    * [junit-team/junit5-samples] (https://github.com/junit-team/junit5-samples)
* AssertJ
    * [AssertJ] (http://joel-costigliola.github.io/assertj/)
    * [joel-costigliola/assertj-examples] (https://github.com/joel-costigliola/assertj-examples/tree/master/assertions-examples/src/test/java/org/assertj/examples)
* Mockito
    * [Mockito] (https://site.mockito.org/)
    * [release notes page] (https://github.com/mockito/mockito/blob/release/2.x/doc/release-notes/official.md)
* Maven
    * [Apache Maven] (https://blogs.apache.org/maven/)

# 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

Mavenは2018/10/24にリリースされた3.6.0を利用しました。
[Release Notes – Maven 3.6.0] (https://maven.apache.org/docs/3.6.0/release-notes.html)

```
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の内容を掲載します。

```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>junit5-demo</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>junit5-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>
    <!-- AssertJ -->
    <assertj.version>3.11.1</assertj.version>
    <!-- Mockito -->
    <mockito.version>2.23.4</mockito.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.jupiter/junit-jupiter-params -->
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-params</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/org.assertj/assertj-core -->
    <dependency>
      <groupId>org.assertj</groupId>
      <artifactId>assertj-core</artifactId>
      <version>${assertj.version}</version>
      <scope>test</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.mockito/mockito-core -->
    <dependency>
      <groupId>org.mockito</groupId>
      <artifactId>mockito-core</artifactId>
      <version>${mockito.version}</version>
      <scope>test</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.mockito/mockito-junit-jupiter -->
    <dependency>
      <groupId>org.mockito</groupId>
      <artifactId>mockito-junit-jupiter</artifactId>
      <version>${mockito.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>
      </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>
      <!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-dependency-plugin -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <version>3.1.1</version>
        <executions>
          <execution>
            <id>tree</id>
            <phase>package</phase>
            <goals>
              <goal>tree</goal>
            </goals>
            <configuration>
              <outputFile>dependency.txt</outputFile>
              <outputType>text</outputType>
            </configuration>
          </execution>
        </executions>
      </plugin>
      <!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-site-plugin -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-site-plugin</artifactId>
        <version>3.7.1</version>
      </plugin>
      <!-- https://mvnrepository.com/artifact/com.github.spotbugs/spotbugs-maven-plugin -->
      <plugin>
        <groupId>com.github.spotbugs</groupId>
        <artifactId>spotbugs-maven-plugin</artifactId>
        <version>3.1.10</version>
        <configuration>
          <xmlOutput>true</xmlOutput>
          <!-- Optional directory to put spotbugs xdoc xml report -->
          <xmlOutputDirectory>target/site</xmlOutputDirectory>
        </configuration>
      </plugin>
    </plugins>
  </build>

  <reporting>
    <plugins>
      <!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-project-info-reports-plugin -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-project-info-reports-plugin</artifactId>
        <version>3.0.0</version>
      </plugin>
      <!-- https://mvnrepository.com/artifact/com.github.spotbugs/spotbugs-maven-plugin -->
      <plugin>
        <groupId>com.github.spotbugs</groupId>
        <artifactId>spotbugs-maven-plugin</artifactId>
        <version>3.1.10</version>
      </plugin>
    </plugins>
  </reporting>

</project>
```

## Maven Plugins

よく利用するプラグインについては、バージョン3.0以上の現時点(2018/12)で最新のバージョンを指定しました。
[Available Plugins] (https://maven.apache.org/plugins/index.html)

### [Maven Clean Plugin] (https://maven.apache.org/plugins/maven-clean-plugin/)

[Release Notes – Maven Clean Plugin – Version 3.1.0] (https://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12317224&version=12337984)

```xml
<!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-clean-plugin -->
<dependency>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-clean-plugin</artifactId>
    <version>3.1.0</version>
</dependency>
```

### [Maven Compiler Plugin] (https://maven.apache.org/plugins/maven-compiler-plugin/)

バージョン3.8.0でJDK 11に関するバグが修正されています。([Unsupported class file major version 55] (https://issues.apache.org/jira/browse/MCOMPILER-342))
[Release Notes – Maven Compiler Plugin – Version 3.8.0] (https://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12317225&version=12341563)

```xml
<!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-compiler-plugin -->
<dependency>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.8.0</version>
</dependency>
```

### [Maven Resources Plugin] (https://maven.apache.org/plugins/maven-resources-plugin/)

[Release Notes – Apache Maven Resources Version 3.1.0] (https://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12317827&version=12336059)

```xml
<!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-resources-plugin -->
<dependency>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-resources-plugin</artifactId>
    <version>3.1.0</version>
</dependency>
```

### [Maven JAR Plugin] (https://maven.apache.org/plugins/maven-jar-plugin/)

[Release Notes – Maven JAR Plugin – Version 3.1.0] (https://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12317526&version=12342349)

```xml
<!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-jar-plugin -->
<dependency>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <version>3.1.1</version>
</dependency>
```

### [Maven Surefire Plugin] (https://maven.apache.org/surefire/maven-surefire-plugin/)

[Using JUnit 5 Platform] (https://maven.apache.org/surefire/maven-surefire-plugin/examples/junit-platform.html)

バージョン2.22.1からJDK 11をサポートしていますが、今回は3.0.0-M3を利用することにしました。

```xml
<!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-surefire-plugin -->
<dependency>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>3.0.0-M3</version>
</dependency>
```

### [Maven Failsafe Plugin] (https://maven.apache.org/surefire/maven-failsafe-plugin/)

FailsafeのバージョンもSurefireに合わせました。

```xml
<!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-failsafe-plugin -->
<dependency>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-failsafe-plugin</artifactId>
    <version>3.0.0-M3</version>
    <scope>test</scope>
</dependency>
```

## JUnit5

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

```xml
<!-- 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-jupiter-api] (https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api)

junit-jupiter-engineを依存関係に組み込むと推移的依存関係としてjunit-jupiter-apiが暗黙的に組み込まれるため、junit-jupiter-apiをpom.xmlに明示的に宣言する必要はありません。

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

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

junit-jupiter-paramsはパラメータ化テスト(Parameterized Tests)が必要な場合に追加するオプショナル機能です。

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

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

```xml
<!-- 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>
```

### [junit-platform-surefire-provider] (https://mvnrepository.com/artifact/org.junit.platform/junit-platform-surefire-provider)

MavenからJUnit5のテストを実行するSurefireプラグインが組み込まれています。
ただし、下記に引用した通りJUnit Platform 1.4で削除される予定です。

> [Maven] (https://junit.org/junit5/docs/current/user-guide/#running-tests-build-maven)
> 
> The custom junit-platform-surefire-provider, which was originally developed by the JUnit team, has been deprecated and is scheduled to be removed in JUnit Platform 1.4. Please use Maven Surefire’s native support instead.

```xml
<!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-surefire-plugin -->
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-surefire-plugin</artifactId>
  <version>2.19.1</version>
  <dependencies>
    <!-- https://mvnrepository.com/artifact/org.junit.platform/junit-platform-surefire-provider -->
    <dependency>
      <groupId>org.junit.platform</groupId>
      <artifactId>junit-platform-surefire-provider</artifactId>
      <version>1.3.2</version>
    </dependency>
  </dependencies>
</plugin>
```

Maven Surefire version 2.22.0以上を利用する場合は、JUnit5をネイティブサポートするので、junit-platform-surefire-providerは不要です。
今回は3.0.0-M3を利用することにしたので使いませんでした。

```xml
<!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-surefire-plugin -->
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-surefire-plugin</artifactId>
  <version>2.22.1</version>
</plugin>
```

## AssertJ

JDK 11やJUnit5との組み合わせで特に気を付けないといけない点はありませんでした。

### [assertj-core] (https://mvnrepository.com/artifact/org.assertj/assertj-core)

```xml
<!-- https://mvnrepository.com/artifact/org.assertj/assertj-core -->
<dependency>
    <groupId>org.assertj</groupId>
    <artifactId>assertj-core</artifactId>
    <version>3.11.1</version>
    <scope>test</scope>
</dependency>
```

## Mockito

Mockitoを利用するために必要な依存関係は下記の通りです。
JUnit5環境で利用する場合はmockito-junit-jupiterが必要になります。

### [mockito-core] (https://mvnrepository.com/artifact/org.mockito/mockito-core)

```xml
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-core -->
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>2.23.4</version>
    <scope>test</scope>
</dependency>
```

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

MockitoExtensionクラス、MockitoSettingsアノテーションが利用できるようになります。

```xml
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-junit-jupiter -->
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-junit-jupiter</artifactId>
    <version>2.23.4</version>
    <scope>test</scope>
</dependency>
```

# テストクラスのひな型

```java
package com.example.demo;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.time.LocalDateTime;
import java.util.List;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.RepeatedTest;
import org.junit.jupiter.api.RepetitionInfo;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInfo;
import org.junit.jupiter.api.TestReporter;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import com.example.demo.service.UserService;

// JUnit5のMockito拡張を有効にする
@ExtendWith(MockitoExtension.class)
@DisplayName("JUnit5 Test Demo")
public class JUnit5DemoTests {

	@Mock(answer = Answers.RETURNS_SMART_NULLS)
	UserService userService;

	// テストメソッドの前に実行される
	@BeforeEach
	// TestInfoを使用して、テストの表示名、テストクラス、テストメソッド、関連付けられているタグなど、現在のテストに関する情報を取得できます
	void setup(TestInfo testInfo) {
		System.out.println("setup: " + testInfo.getDisplayName());
	}

	// テストメソッドの後に実行される
	@AfterEach
	void tearDown() {
		System.out.println("tearDown");
	}

	@Test
	void userItems() {
		when(userService.getItems(eq(100L))).thenReturn(List.of("Apple", "Banana", "Cherry"));

		List<String> items = userService.getItems(100L);
		assertThat(items).hasSize(3);

		verify(userService).getItems(eq(100L));
	}

	@Test
	@DisplayName("demo1をテストする")
	// TestReporterを使用して現在のテスト実行に関する追加データを公開することができます
	// データはIDEによって表示されるかレポートに含まれるようになります
	void demo1(TestReporter reporter) {
		reporter.publishEntry("demo1のテスト");
		// demo1のテスト
		reporter.publishEntry("demo1 key", "demo1 value");
	}

	@Nested
	@DisplayName("Hoge Tests")
	class HogeTests {

		@RepeatedTest(value = 3, name = RepeatedTest.LONG_DISPLAY_NAME)
		@DisplayName("hogeをテストする")
		// RepetitionInfoを使用して、現在の繰り返しおよび対応する@RepeatedTestの繰り返しの総数に関する情報を取得できます
		void hoge(RepetitionInfo info) {
			System.out.println("hoge current:" + info.getCurrentRepetition() + " total:" + info.getTotalRepetitions());
		}

	}

	@Nested
	@DisplayName("Fuga Tests")
	class FugaTests {

		@ParameterizedTest
		@CsvSource({ "foo, 10000, 100, 2018-12-30T00:00:00.000", "bar, 20000, 200, 2018-12-30T12:00:00.000",
				"baz, 30000, 300, 2018-12-30T23:00:00.000" })
		@DisplayName("fugaをテストする")
		void fuga(String first, int second, long third, LocalDateTime fourth) {
			System.out.println(
					"fuga first:" + first + " second:" + second + " third:" + third + " fourth:" + fourth.toString());
		}

	}

}
```

![junit5.png](https://qiita-image-store.s3.amazonaws.com/0/22772/22f44657-5490-c057-a433-0028b37d7570.png)

## JUnit5

### [Annotations] (https://junit.org/junit5/docs/current/user-guide/#writing-tests-annotations)

|JUnit5             |@Target          |JUnit4's         |
|:------------------|:----------------|:----------------|
|@Test              |ANNOTATION_TYPE<br>METHOD  |@Test            |
|@ParameterizedTest |ANNOTATION_TYPE<br>METHOD  |                 |
|@RepeatedTest      |ANNOTATION_TYPE<br>METHOD  |                 |
|@TestFactory       |ANNOTATION_TYPE<br>METHOD  |                 |
|@TestInstance      |TYPE                       |                 |
|@TestTemplate      |ANNOTATION_TYPE<br>METHOD  |                 |
|@DisplayName       |TYPE<br>METHOD             |                 |
|@BeforeEach        |ANNOTATION_TYPE<br>METHOD  |@Before          |
|@AfterEach         |ANNOTATION_TYPE<br>METHOD  |@After           |
|@BeforeAll         |ANNOTATION_TYPE<br>METHOD  |@BeforeClass     |
|@AfterAll          |ANNOTATION_TYPE<br>METHOD  |@AfterClass      |
|@Nested            |TYPE                       |                 |
|@Tag               |TYPE<br>METHOD             |                 |
|@Disabled          |TYPE<br>METHOD             |@Ignore          |
|@ExtendWith        |TYPE<br>METHOD             |                 |

### [Test Classes and Methods] (https://junit.org/junit5/docs/current/user-guide/#writing-tests-classes-and-methods)

> A test method is any instance method that is directly or meta-annotated with @Test, @RepeatedTest, @ParameterizedTest, @TestFactory, or @TestTemplate.

#### @Test

```java
@Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@API(status = STABLE, since = "5.0")
@Testable
public @interface Test {
}
```

#### @TestTemplate

```java
@Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@API(status = STABLE, since = "5.0")
@Testable
public @interface TestTemplate {
}
```

#### @TestTemplate

```java
@Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@API(status = STABLE, since = "5.0")
@Testable
public @interface TestTemplate {
}
```

#### @Testable

```java
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@API(status = STABLE, since = "1.0")
public @interface Testable {
}
```

### [Repeated Tests] (https://junit.org/junit5/docs/current/user-guide/#writing-tests-repeated-tests)

#### @RepeatedTest

```java
@Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@API(status = STABLE, since = "5.0")
@TestTemplate
public @interface RepeatedTest {
//...
}
```

### [Parameterized Tests] (https://junit.org/junit5/docs/current/user-guide/#writing-tests-parameterized-tests)

#### @ParameterizedTest

```java
@Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@API(status = EXPERIMENTAL, since = "5.0")
@TestTemplate
@ExtendWith(ParameterizedTestExtension.class)
public @interface ParameterizedTest {
//...
}
```

パラメータソースに指定に使用するアノテーション

|Annotation       |Source |
|:----------------|:-----------------------------------|
|@ValueSource     |配列 |
|@EnumSource      |Enum |
|@MethodSource    |テストクラス、外部クラスのファクトリメソッド |
|@CsvSource       |カンマ区切りの文字列 |
|@CsvFileSource   |クラスパス上のCSVファイル |
|@ArgumentsSource |ArgumentsProviderの実装クラス |

### [Extension Model] (https://junit.org/junit5/docs/current/user-guide/#extensions)

> In contrast to the competing Runner, @Rule, and @ClassRule extension points in JUnit 4, the JUnit Jupiter extension model consists of a single, coherent concept: the Extension API. Note, however, that Extension itself is just a marker interface.

#### @ExtendWith

@ExtendWithで宣言的(declaratively)に拡張機能を登録します。

```java
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Repeatable(Extensions.class)
@API(status = STABLE, since = "5.0")
public @interface ExtendWith {
//...省略
}
```

#### @RegisterExtension

@RegisterExtensionでプログラム的(programmatically)に拡張機能を登録します。

```java
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@API(status = STABLE, since = "5.1")
public @interface RegisterExtension {
}
```

## Mockito

下記のようにstaticインポートしておくと便利です。

```java
import static org.mockito.Mockito.*;
```

必要であればMatchersもstaticインポートしておきます。

* [Class ArgumentMatchers] (https://static.javadoc.io/org.mockito/mockito-core/2.23.4/org/mockito/ArgumentMatchers.html)
* [Class AdditionalMatchers] (https://static.javadoc.io/org.mockito/mockito-core/2.23.4/org/mockito/AdditionalMatchers.html)

```java
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.AdditionalMatchers.*;
```

### [MockitoExtension] (https://static.javadoc.io/org.mockito/mockito-junit-jupiter/2.23.4/org/mockito/junit/jupiter/MockitoExtension.html)

> Extension that initializes mocks and handles strict stubbings. This extension is the JUnit Jupiter equivalent of our JUnit4 MockitoJUnitRunner.

```java
@ExtendWith(MockitoExtension.class)
```

### [MockitoSettings] (https://static.javadoc.io/org.mockito/mockito-junit-jupiter/2.23.4/org/mockito/junit/jupiter/MockitoSettings.html)

> Annotation that can configure Mockito as invoked by the MockitoExtension.

```java
@MockitoSettings
```

#### Strictness

|Strictness   |behavior              |
|:------------|:---------------------|
|LENIENT      |Mockito 1.xと同じ動作. |
|WARN         |Mockito 2.xと同じ動作. |
|STRICT_STUBS |Default. 計画ではMockito 3.xのデフォルトの動作の予定. |

## AssertJ

JUnit5環境でのAssertJの書き方に特別変わった点はないようなので省略します。

```java
// entry point for all assertThat methods and utility methods (e.g. entry)
import static org.assertj.core.api.Assertions.*;
```