Workaround for Command Line Runner to work with JUnit in Spring Boot

Background and problems

In Spring Boot, use Command Line Runner You can develop applications that run from the command line.

But in an application that uses CommandLineRunner When you run a test in JUnit, not only the test code but also the processing of CommandLineRunner itself is executed.

I felt a little crazy, so I wanted to avoid it somehow.

Execution environment

Execution code and test and output

Execution code

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!!";
  }
}

Test code

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());
	}
}

The result of running JUnit is as follows.

Execution result


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

abridgement

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

When I run JUnit, it outputs with CommandLineRunner

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

Is output. I want only the test code to work, but even CommandLineRunner has been executed.

Workaround

I don't want to run CommandLineRunner when running JUnit, so I'll look for a way to do it. Try it referring to the following. https://stackoverflow.com/questions/29344313/prevent-application-commandlinerunner-classes-from-executing-during-junit-test

Use Profile annotation

This method is omitted because there are easy-to-understand articles on stackoverflow and Qiita. https://qiita.com/ftsan/items/80b00f8fb8129ecbdf97

However, I wonder if there is a different method I tried to see if there was another way that I could just fix the test code.

Use ContextConfiguration annotation

In the test code SampleOutputTest.java Annotate SpringBootTest ContextConfiguration(classes = SampleApplication.class, initializers = ConfigFileApplicationContextInitializer.class) Modify to annotation.

SampleOutputTest.java


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

Now when you run the test, you can test it without running CommandLineRunner. The classes = SampleApplication.class part specifies the class where the main method is located.

Execution result


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

Omitted below

Now you can test without running CommandLineRunner with just the modification of the test code. Does it mean that SpringBootTest is loading various settings, but ContextConfiguration does not load all the settings?

https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html If you read this document carefully, you can find it at 43.4 Test Utilities. It was written that you should use this if you do not need to use all the functions of SpringBootTest.


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

Recommended Posts

Workaround for Command Line Runner to work with JUnit in Spring Boot
Settings for connecting to MySQL with Spring Boot + Spring JDBC
Execution of initial processing using Spring Boot Command Line Runner
[Java] LINE integration with Spring Boot
Spring.messages.fallback-to-system-locale: false is required to default message.properties for i18n support in Spring boot
[Java] How to test for null with JUnit
How to use MyBatis2 (iBatis) with Spring Boot 1.4 (Spring 4)
How to use built-in h2db with spring boot
Try to implement login function with Spring Boot
How to add a classpath in Spring Boot
How to perform UT with Excel as test data with Spring Boot + JUnit5 + DBUnit
[Java] Hello World with Java 14 x Spring Boot 2.3 x JUnit 5 ~
How to bind to property file in Spring Boot
Try to automate migration with Spring Boot Flyway
[Java] Article to add validation with Spring Boot 2.3.1.
I wanted to gradle spring boot with multi-project
[Introduction to Spring Boot] Authentication function with Spring Security
Include external jar in package with Spring boot2 + Maven3
How to set Dependency Injection (DI) for Spring Boot
How to write a unit test for Spring Boot 2
Automatically map DTOs to entities with Spring Boot API
[JUnit 5 compatible] Write a test using JUnit 5 with Spring boot 2.2, 2.3
How to create a Spring Boot project in IntelliJ
[Spring Boot] How to create a project (for beginners)
SSO with GitHub OAuth in Spring Boot 1.5.x environment
[JUnit 5] Write a validation test with Spring Boot! [Parameterization test]
How to use CommandLineRunner in Spring Batch of Spring Boot
Until you start development with Spring Boot in eclipse 1
Introduce swagger-ui to REST API implemented in Spring Boot
How to boot by environment with Spring Boot of Maven
Until you start development with Spring Boot in eclipse 2
Attempt to SSR Vue.js with Spring Boot and GraalJS
I wrote a test with Spring Boot + JUnit 5 now
Database environment construction with Docker in Spring boot (IntellJ)
Try to work with Keycloak using Spring Security SAML (Spring 5)
Download with Spring Boot
How to use the same Mapper class in multiple data sources with Spring Boot + MyBatis
I want to control the maximum file size in file upload for each URL in Spring Boot
Let's find out how to receive in Request Body with REST API of Spring Boot
Steps required to issue an asynchronous event for Spring Boot
Output embedded Tomcat access log to standard output with Spring Boot
How to change application.properties settings at boot time in Spring boot
Extract SQL to property file with jdbcTemplate of spring boot
Until INSERT and SELECT to Postgres with Spring boot and thymeleaf
How to call and use API in Java (Spring Boot)
Connect to database with spring boot + spring jpa and CRUD operation
Flow until output table data to view with Spring Boot
Use thymeleaf3 with parent without specifying spring-boot-starter-parent in Spring Boot
I tried to get started with Swagger using Spring Boot
Use Spring Test + Mockito + JUnit 4 for Spring Boot + Spring Retry unit tests
Use @ControllerAdvice, @ExceptionHandler, HandlerExceptionResolver in Spring Boot to catch exceptions
How to control transactions in Spring Boot without using @Transactional
[Java] Sample project for developing web applications with Spring Boot
Set context-param in Spring Boot
Try Spring Boot from 0 to 100.
Generate barcode with Spring Boot
Hello World with Spring Boot
Implement GraphQL with Spring Boot
Get started with Spring boot
Hello World with Spring Boot!
Spring Boot 2 multi-project in Gradle