Barney
Barney

Reputation: 915

SpringExtension without an explicit configuration?

I have a JUnit5 test with SpringExtension. All I need is environment variables to be injected via Spring's @Value:

@ExtendWith(SpringExtension.class)
class MyTest {
    @Value("${myValue}") String myValue;
    ...

Doing so, I get an error saying:

Failed to load ApplicationContext Caused by: java.lang.IllegalStateException: Neither GenericGroovyXmlContextLoader nor AnnotationConfigContextLoader was able to load an ApplicationContext

Of course, Spring needs to have a context configuration, so I put it into the test code:

@ExtendWith(SpringExtension.class)
@ContextConfiguration
class MyTest {
    @Value("${myValue}") String myValue;

    @Configuration
    static class TestConfig { /*empty*/ }
    ...

While this works, it looks like a lot of unnecessary boilerplate code to me. Is there a simpler way?

UPDATE

One shorter variant would be to use @SpringJUnitConfig which brings both @ContextConfiguration and @ExtendWith(SpringExtension.class) out of the box.

But a configuration class (even an empty one) is still needed.

Upvotes: 2

Views: 6008

Answers (3)

Sam Brannen
Sam Brannen

Reputation: 31247

As has been pointed out in other answers and comments, you need to specify an empty configuration source, specifically a @Configuration class, XML config file, Groovy config file, or ApplicationContextInitializer.

The easiest way to do that is to create your own composed annotation that predefines the empty configuration.

If you introduce the following @EmptySpringJUnitConfig annotation in your project, you can use it (instead of @SpringJUnitConfig) wherever you want an empty Spring ApplicationContext.

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Inherited
@SpringJUnitConfig(EmptySpringJUnitConfig.Config.class)
public @interface EmptySpringJUnitConfig {
    @Configuration
    class Config {
    }
}

Upvotes: 2

M. Deinum
M. Deinum

Reputation: 124898

You cannot run a Spring based test without a configuration. The Spring Test Context Framework (TCF) expects/requires an ApplicationContext. To create an ApplicationContext a form configuration (xml, Java) needs to be present.

You have 2 options to make it work

  1. Use an empty configuration, emtpy XML file or empty @Configuration class
  2. Write a custom ContextLoader which creates an empty application context.

Option 1 is probably the easiest to achieve. You could create a global empty configuration and refer that from the @ContextConfiguration.

Upvotes: 1

Anatoliy Korovin
Anatoliy Korovin

Reputation: 436

In SpringBoot to run a spring application context, you need to use the @SpringBootTest annotation on the test class:

@ExtendWith(SpringExtension.class)
@SpringBootTest
class MyTest {
    @Value("${myValue}") String myValue;
    ...

UPDATED:

Or if you use just a Spring Framework (without spring boot) then test configuration depends on a version of the spring framework which you use, and on the spring configuration of your project.

You can set configuration files by the using of @ContextConfiguration, if you use java config then it will be something like that:

@ContextConfiguration(classes = AppConfig.class)
@ExtendWith(SpringExtension.class)
class MyTest {
    ...

or if you use xml configuration:

@ContextConfiguration("/test-config.xml")
@ExtendWith(SpringExtension.class)
class MyTest {
    ...

both of these depends on your project configuration structure and list of beans which you need in tests.

More details about context configuration: https://docs.spring.io/spring/docs/current/spring-framework-reference/testing.html#spring-testing-annotation-contextconfiguration

If you use the Spring Framework older then 5.0 then you can find useful this library: https://github.com/sbrannen/spring-test-junit5

Upvotes: 0

Related Questions