3 min to read
Java Spring Boot: Exclude CommandLineRunner in JUnit

This will is a quick post on a recent testing problem I faced while programming a Java console app with Spring framework.
My console app class uses the Spring interface CommandLineRunner
,
see Spring API.
The reason we use this, is that any beans implementing this interface will be executed automatically by the SpringApplication
.
This reduces boiler-plate code and uses Inversion-of-Control (IoC)
if we want to load a different app.
The structure of my console app looks like the following:
@SpringBootApplication
public class Application {
@Bean
public CommandLineRunner getConsoleApp() {return new MyConsoleApp();}
}
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(Application.class, args);
}
}
class MyConsoleApp implements CommandLineRunner {
@Override
public void run(String... args) throws Exception { ... }
}
Testing with JUnit
Since we are using IoC and dependency injections, we need to setup
the ApplicationContext before executing our tests.
This is generally done by adding the annotation @SpringBootTest
to
our test class.
If we want to test a part of the code, there are times when we don’t want to
run the console application.
But the problem is that the SpringApplication will execute
the CommandLineRunner
bean.
While searching online for a solution, I found this
post
and
spring.io
that describe @Configuration
and @TestConfiguration
classes, nested inside
the JUnit test class.
Extracted from docs.spring.io:
If you want to customize the primary configuration, you can use a nested @TestConfiguration class. Unlike a nested @Configuration class, which would be used instead of your application’s primary configuration, a nested @TestConfiguration class is used in addition to your application’s primary configuration.
In short,
- Using
@Configuration
will override the primary source of Spring configuration. - Using
@TestConfiguration
will add new configuration (beans) to the original configuration. It will not override existing bean definitions.
Because the console app is annotated with @SpringBootApplication
, I decided
to create a nested @Configuration
class that extends
the original configuration held by Application
.
Then, I override the bean configuration for CommandLineRunner
.
Here’s how my code looks like in my test class (using JUnit 5):
@SpringBootTest
class TimeVolumeProfileImporterTest {
@Configuration
static class MyTestConfiguration extends Application {
@Bean
@Override
public CommandLineRunner getConsoleApp() { return null; }
}
@Test
void testMethod() { ... }
}
For this test class, the SpringApplication
will not run the CommandLineRunner
,
but IoC and dependency injections are still applied.
Alternative solutions
Other solutions are:
- Load another configuration class using
@ContextConfiguration
. - Tags the bean annotations with
@Profile("!test")
for the CommandLineRunner, and@ActiveProfile("test")
on the JUnit test class.