10
9

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.

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

Last updated at Posted at 2018-06-13

背景と問題点

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

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

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

実行環境

  • Spring Boot-2.0.2.RELEASE
  • JUnit-4.12

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

実行コード

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!!!");
  }
}
SampleOutput.java
package com.example.demo;

public class SampleOutput {

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

テストコード

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) のアノテーションに修正します。

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の全部の機能を使う必要がなかったらこれを使うといいよって書いてありましたね。


@ContextConfiguration(classes = Config.class,
	initializers = ConfigFileApplicationContextInitializer.class)
10
9
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
10
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?