【问题标题】:Spring Boot test does not start context or load dependenciesSpring Boot 测试不启动上下文或加载依赖项
【发布时间】:2020-07-19 07:07:25
【问题描述】:

一个非常初学者的问题,但我无法通过。我有一个基本的 Spring Boot 应用程序和一个连接到云图集实例的 Spring Data MongoDB 存储库。问题是在我的 Spring Boot 测试中,我的存储库没有自动装配,并且没有创建嵌入式 MongoDB 实例。如果我启动 Spring Boot 应用程序并在主类中自动装配存储库,那么它可以工作。为什么它在我的测试中不起作用?

这是我的测试课:

@DataMongoTest
@ExtendWith(SpringExtension.class)
public class SampleServiceTest{


    @Autowired
    private SampleRepository sampleRepository;

    @Test
    public void shouldCreateSample(){
        sampleRepository.save(new Sample());
    }
}

这是我的 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">
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.2.RELEASE</version>
        <relativePath></relativePath>
    </parent>
    <modelVersion>4.0.0</modelVersion>



    <groupId>com.comand</groupId>
    <artifactId>business-owner-service</artifactId>
    <version>1.0-SNAPSHOT</version>
    <description>API Gateway</description>

    <properties>
        <maven.compiler.target>1.8</maven.compiler.target>
        <maven.compiler.source>1.8</maven.compiler.source>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-client</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <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>
        </dependency>
        <dependency>
            <groupId>de.flapdoodle.embed</groupId>
            <artifactId>de.flapdoodle.embed.mongo</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-parent</artifactId>
                <version>Greenwich.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

【问题讨论】:

    标签: spring spring-boot junit spring-data-mongodb spring-boot-test


    【解决方案1】:

    当您使用@Autowired 注释时,基本上您是在将变量映射到应用程序上下文中存在的对象。请记住,应用程序上下文是在您启动 spring boot 应用程序时创建的。所有具有注解 @Service@Repository@Component 的类都在应用程序上下文中实例化。

    我假设SampleRepository 具有以下注释之一:@Service@Repository@Component@Repository。而当你启动 spring boot 应用程序时,应用程序上下文被创建并实例化了SampleRepository 类。

    @Autowire 注释将在应用程序上下文中创建的对象与具有注释@Autowire 的变量映射。

    它在您的测试中不起作用的原因是SampleRepository 类的对象不存在。而且你不能将它映射到你用@Autowire注释的变量。

    您可以通过两种方式解决此问题:

    1. 第一个解决方案是在运行测试类时创建应用程序上下文。我建议不要在实例化所有对象的情况下加载整个应用程序上下文。最好只加载测试类中需要的应用程序上下文的一部分。
    @EnableConfigurationProperties(SampleRepository.class)
       public class TestConfiguration {
    }
    
    @ExtendWith(SpringExtension.class)
    @SpringBootTest(classes = { TestConfiguration.class })
    public class SampleServiceTest{
    }
    
    1. 第二种解决方法是修改注解@DataMongoTest如下:
    @DataMongoTest(includeFilters = @Filter(Service.class))
    //or
    @DataMongoTest(includeFilters = @Filter(Component.class))
    

    使用 @DataMongoTest 注释将禁用完全自动配置,而是仅应用与 MongoDB 测试相关的配置。所以用@Services,Component注解的类不会被实例化。 includeFilters 是一组过滤器,可用于将过滤后的 bean 添加到应用程序上下文中。

    我怀疑您使用 @Service@Component 注释对 SampleRepository 类进行了注释,这就是它没有创建 SampleRepository 类的实例的原因。

    我在 git repo 中查看了您的代码,并修改如下:

    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringBootTest
    public class BusinessOwnerServiceTest {
    
        @Autowired
        private BusinessOwnerService businessOwnerService;
    
        @Autowired
        private BusinessOwnerRepository businessOwnerRepository;
    
        @Test
        public void shouldCreateNewBusinessOwner(){
           businessOwnerService.findBusinessOwnerByEmail("EMAIL@gmail.com");    
        }
    
    }
    
    

    下面是结果:

    下面是第二种解决方案:

    @RunWith(SpringJUnit4ClassRunner.class)
    @DataMongoTest(includeFilters = @Filter(Service.class))
    public class BusinessOwnerServiceTest {
    
        @Autowired
        private BusinessOwnerService businessOwnerService;
    
        @Autowired
        private BusinessOwnerRepository businessOwnerRepository;
    
        @Test
        public void shouldCreateNewBusinessOwner(){
           businessOwnerService.findBusinessOwnerByEmail("EMAIL@gmail.com");    
        }
    
    }
    

    以下是第二种解决方案的结果:

    【讨论】:

    • 嗨。存储库接口使用@Repository 进行注释。我尝试了您的解决方案,但它们不起作用。我的 git 分支是这样的:github.com/tudorgrig/comand/tree/4-persistency-layer
    • 您需要添加@RunWith(SpringJUnit4ClassRunner.class),它会起作用。
    猜你喜欢
    • 1970-01-01
    • 2021-10-19
    • 1970-01-01
    • 1970-01-01
    • 2021-01-04
    • 2020-01-09
    • 1970-01-01
    • 1970-01-01
    • 2018-07-04
    相关资源
    最近更新 更多