SpringBootでのJUnitでCommandLineRunnerが動くことの回避策

# 背景と問題点
SpringBootではCommandLineRunnerを使って
コマンドラインから実行するアプリケーションを開発できます。

しかし、CommandLineRunnerを使ったアプリケーションで
JUnitでテストを実行すると、テストコードだけでなくCommandLineRunnerそのものの処理まで実行されてしまいます。

ちょっといけてない感じがしたのでどうにか回避したかったのです。

# 実行環境
 - Spring Boot-2.0.2.RELEASE
 - JUnit-4.12

# 実行コードとテストと出力
実行コード

```java:SampleApplication.java
package com.example.demo;

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SampleApplication implements CommandLineRunner {

  public static void main(String[] args) {
    SpringApplication.run(SampleApplication.class, args);
  }

  @Override
  public void run(String... arg) {
    SampleOutput sample = new SampleOutput();
    System.out.println(sample.sayTest());
    System.out.println("!!!Sample CommandLineRunner Start!!!");
  }
}
```


```java:SampleOutput.java
package com.example.demo;

public class SampleOutput {

  public String sayTest() {
    return "test!!";
  }
}
```

テストコード

```java:SampleOutputTest
package com.example.demo;

import static org.junit.Assert.assertEquals;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class SampleOutputTest {

	@Test
	public void testTest() {
	  SampleOutput sample = new SampleOutput();
	  assertEquals("test!!", sample.sayTest());
	}
}
```

JUnitを実行した結果は以下です。

```:実行結果
07:42:33.780 [main] DEBUG org.springframework.test.context.junit4.SpringJUnit4ClassRunner - SpringJUnit4ClassRunner constructor called with [class com.example.demo.SampleOutputTest]

省略

2018-06-13 07:42:34.458  INFO 6564 --- [           main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@2df9b86: startup date [Wed Jun 13 07:42:34 JST 2018]; root of context hierarchy
2018-06-13 07:42:35.128  INFO 6564 --- [           main] com.example.demo.SampleOutputTest        : Started SampleOutputTest in 0.972 seconds (JVM running for 1.867)
test!!
!!!Sample CommandLineRunner Start!!!
2018-06-13 07:42:35.190  INFO 6564 --- [       Thread-2] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@2df9b86: startup date [Wed Jun 13 07:42:34 JST 2018]; root of context hierarchy

```

JUnitを実行するとCommandLineRunnerで出力している

```
test!!
!!!Sample CommandLineRunner Start!!!
```

が出力されています。
テストコードだけ動作してほしいのですが、CommandLineRunnerまで実行されてしまっています。


## 回避策
JUnit実行時にCommandLineRunnerを実行したくないため、そのやり方を探します。
以下を参考に試します。
https://stackoverflow.com/questions/29344313/prevent-application-commandlinerunner-classes-from-executing-during-junit-test


### Profileのアノテーションを使う
この方法は、stackoverflowやQiitaにもわかりやすい記事があるので割愛します。
https://qiita.com/ftsan/items/80b00f8fb8129ecbdf97


ただ、違う方法ないかなーと
テストのコードの修正だけですむ他の方法がないか試してみました。

### ContextConfigurationのアノテーションを使う

テストコードの`SampleOutputTest.java`で
`SpringBootTest` のアノテーションを 
`ContextConfiguration(classes = SampleApplication.class, 
initializers = ConfigFileApplicationContextInitializer.class)
`のアノテーションに修正します。

```java:SampleOutputTest.java
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = SampleApplication.class, 
initializers = ConfigFileApplicationContextInitializer.class)
public class SampleOutputTest {
```

これでテストを実行すると、CommandLineRunnerを実行せずにテストができます。
`classes = SampleApplication.class`の部分はmainメソッドがあるクラスを指定しています。

```:実行結果
07:44:49.301 [main] DEBUG org.springframework.test.context.junit4.SpringJUnit4ClassRunner - SpringJUnit4ClassRunner constructor called with [class com.example.demo.SampleOutputTest]

以下省略
```

これでテストコードの方の修正だけでCommandLineRunnerを実行せずにテストができました。
`SpringBootTest`がいろんな設定を読み込んでいるのに対して`ContextConfiguration`にすると全部の設定を読み込んではいないということなのでしょうかね。




https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html
こちらのドキュメントをよく読んだら、43.4 Test Utilitiesのところに
`SpringBootTest`の全部の機能を使う必要がなかったらこれを使うといいよって書いてありましたね。

```java

@ContextConfiguration(classes = Config.class,
	initializers = ConfigFileApplicationContextInitializer.class)
```