背景と問題点
SpringBootではCommandLineRunnerを使って
コマンドラインから実行するアプリケーションを開発できます。
しかし、CommandLineRunnerを使ったアプリケーションで
JUnitでテストを実行すると、テストコードだけでなくCommandLineRunnerそのものの処理まで実行されてしまいます。
ちょっといけてない感じがしたのでどうにか回避したかったのです。
実行環境
- Spring Boot-2.0.2.RELEASE
- JUnit-4.12
実行コードとテストと出力
実行コード
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!!!");
}
}
package com.example.demo;
public class SampleOutput {
public String sayTest() {
return "test!!";
}
}
テストコード
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)
のアノテーションに修正します。
@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
の全部の機能を使う必要がなかったらこれを使うといいよって書いてありましたね。
@ContextConfiguration(classes = Config.class,
initializers = ConfigFileApplicationContextInitializer.class)