Spring-boot + JUnit5でconfigの中身を上書きする

# はじめに
Mockito使えばすぐ使えますが、ちょっとメモしたかったので記事にしました。

# 環境
Java9
Spring-boot 2.0.0.RELEASE

# 今回の目標
Serviceクラス内に設定したConfigをテスト用Configファイル読み込みではなく、Junit上から書き換えを行います。

# pom.xml
他の記事等でも書かれていますが、いつも調べるのでついでに記載しておきます。

``` xml
<?xml version="1.0" encoding="UTF-8"?>
<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.tasogarei</groupId>
	<artifactId>junit-test</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>junit-test</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.0.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>9</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.platform</groupId>
            <artifactId>junit-platform-launcher</artifactId>
            <version>1.0.1</version>
            <scope>test</scope>
        </dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>


</project>
```

# Service
謎のprivate methodがありますが、別の事もこの後試したいのであるだけです。
気にしないでください。

``` java
package com.tasogarei.app.service;

import java.util.Properties;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.tasogarei.app.util.TestConfig;

@Service
public class TestService {
    
    @Autowired
    private TestConfig config;
    
    public String getString() {
        return getStr();
    }
    
    private String getStr() {
        return config.getTest();
    }    
}
```

# config
今回はConfigurationアノテーションベースでやっていきます。

``` java
package com.tasogarei.app.util;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

@Configuration
public class TestConfig {
    @Value("${app.test}") 
    private String test;

    public String getTest() {
        return test;
    }

    public void setTest(String test) {
        this.test = test;
    }
}
```

``` application.properties
app.test=configtest
```

`application.properties`に適当な値を入れておきます。

# Testクラス
`@MockBean`でMock化しておいて`Mockito.when().then()`で書き換えたい内容をやっておけばテストでMockにした方が使われるのでこれでオッケーです。
`when`で指定したメソッドの戻り値がクラスでも`then`で書き換えたいクラスを入れておけばそのクラスが使われるので、それでテスト可能です。
もちろん型は同じでなければいけません。

``` java
package com.tasogarei.app.service;

import static org.junit.jupiter.api.Assertions.assertEquals;

import java.util.Properties;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.junit.jupiter.SpringExtension;

import com.tasogarei.app.util.TestConfig;

@ExtendWith(SpringExtension.class)
@SpringBootTest
public class TestServiceTest {

    @Autowired
    private TestService testService;
    
    @MockBean
    private TestConfig testConfig;
    
    @Test
    public void test() {
        Mockito.when(testConfig.getTest()).thenReturn("hogehoge123");
        assertEquals(testService.getString(), "hogehoge123");
    }
}
```

# 最後に
テストメソッドで書き換えを行うのは微妙な気がするので、事前処理で出来るものはそちらでやった方が良いと思います。