How to make Spring's @Autowired to work in JUnit 5 extensions?

25,559

JUnit 5 extensions can not operate on other extensions, just on test classes.

So...

@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class SomeExtension implements BeforeEachCallback {

    @Autowired
    SomeBean bean;

    @Override
    public void beforeEach(ExtensionContext context) {
        assertNotNull(bean);
    }

}

@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ExtendWith(SomeExtension.class)
class SomeTest {

    @Test
    void nothingTest() {
    }

}

... can not work. This would:

public class SomeExtension implements BeforeEachCallback {

    @Override
    public void beforeEach(ExtensionContext context) {
        // [...]
    }

}

@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ExtendWith(SomeExtension.class)
class SomeTest {

    @Autowired
    SomeBean bean;

    @Test
    void nothingTest() {
    }

}

If you can explain why you need a bean in your extension, we may be able to help you find a fix for that, too.

Share:
25,559
Theemathas Chirananthavat
Author by

Theemathas Chirananthavat

Updated on August 07, 2020

Comments

  • Theemathas Chirananthavat
    Theemathas Chirananthavat over 3 years

    I have a Spring Boot application, and I am trying to use @Autowired in a JUnit 5 extension. However, I cannot get it to work. (The @Autowired field is null.) Can anybody help?

    Below is code that demonstrates the problem I'm having (the important parts are SomeExtension and SomeTest. As written, mvn test causes the test to fail in beforeEach. Sorry if I'm including too much.

    src/test/java/somepackage/SomeExtension.java:

    package somepackage;
    
    import org.junit.jupiter.api.extension.BeforeEachCallback;
    import org.junit.jupiter.api.extension.ExtendWith;
    import org.junit.jupiter.api.extension.ExtensionContext;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit.jupiter.SpringExtension;
    
    import static org.junit.jupiter.api.Assertions.assertNotNull;
    
    @ExtendWith(SpringExtension.class)
    @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
    public class SomeExtension implements BeforeEachCallback {
        @Autowired
        SomeBean bean;
    
        @Override
        public void beforeEach(ExtensionContext context) {
            assertNotNull(bean);
        }
    }
    

    src/test/java/somepackage/SomeTest.java:

    package somepackage;
    
    import org.junit.jupiter.api.Test;
    import org.junit.jupiter.api.extension.ExtendWith;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit.jupiter.SpringExtension;
    
    
    @ExtendWith(SpringExtension.class)
    @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
    @ExtendWith(SomeExtension.class)
    class SomeTest {
        @Test
        void nothingTest() {
        }
    }
    

    src/main/java/somepackage/SomeBean.java

    package somepackage;
    
    import org.springframework.stereotype.Component;
    
    @Component
    public class SomeBean {
    }
    

    src/main/java/somepackage/MainClass.java

    package somepackage;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication
    public class MainClass {
        public static void main(String[] args) {
            SpringApplication.run(MainClass.class, args);
        }
    }
    

    pom.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>fooGroupId</groupId>
        <artifactId>barArtifactId</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.0.3.RELEASE</version>
        </parent>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
                <exclusions>
                    <exclusion>
                        <!-- Don't include Junit 4 -->
                        <groupId>junit</groupId>
                        <artifactId>junit</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <dependency>
                <groupId>org.junit.jupiter</groupId>
                <artifactId>junit-jupiter-engine</artifactId>
                <version>5.2.0</version>
                <scope>test</scope>
            </dependency>
        </dependencies>
    
        <properties>
            <java.version>1.8</java.version>
        </properties>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
    
                <plugin>
                    <!--
                    This is copied from https://junit.org/junit5/docs/current/user-guide/#running-tests-build-maven
                    This allows the surefire plugin to be able to find Junit 5 tests, so `mvn test` works.
                    -->
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>2.21.0</version>
                    <dependencies>
                        <dependency>
                            <groupId>org.junit.platform</groupId>
                            <artifactId>junit-platform-surefire-provider</artifactId>
                            <version>1.2.0</version>
                        </dependency>
                    </dependencies>
                </plugin>
            </plugins>
        </build>
    
        <repositories>
            <repository>
                <id>spring-releases</id>
                <url>https://repo.spring.io/libs-release</url>
            </repository>
        </repositories>
        <pluginRepositories>
            <pluginRepository>
                <id>spring-releases</id>
                <url>https://repo.spring.io/libs-release</url>
            </pluginRepository>
        </pluginRepositories>
    
    </project>
    

    I'm also having similar issues with @Value. If the solution also works for that, it would be great.

    Thank you.