首页 > 解决方案 > 春季启动:@ConfigurationProperties 对测试不满意

问题描述

我在执行测试时遇到了这个异常:

UnsatisfiedDependencyException:创建名称为“net.gencat.transversal.espaidoc.mongo.GridFSTest”的bean时出错:通过字段“resourceProperties”表示的依赖关系不满足;嵌套异常是 org.springframework.beans.factory.NoSuchBeanDefinitionException:没有“net.gencat.transversal.espaidoc.ResourcesConfigProperties”类型的合格 bean 可用:预计至少有 1 个有资格作为自动装配候选者的 bean。

所以,我认为信息很清楚:ResourcesConfigProperties is not satisfied

我的测试:

RunWith(SpringRunner.class)
@SpringBootTest()
public class GridFSTest {

    @Autowired
    private GridFsTemplate gridFsTemplate;

    @Autowired
    private ResourcesConfigProperties resourceProperties;

    public URL getHugeResource() {
        try {
            return Paths
                .get(this.resourceProperties.getHuge())
                .toUri()
                .toURL();
        } catch (MalformedURLException e) {
            return null;
        }
    }

    @Test
    public void storeHugeFile() throws IOException {
        URL resource = this.getHugeResource();

        this.gridFsTemplate.store(
            resource.openStream(),
            resource.getPath(),
            "mime"
        );
    }
}

并且ResourcesConfigProperties是:

@ConfigurationProperties(prefix = "files")
public class ResourcesConfigProperties {

    private String huge;

    /**
     * @return the huge
     */
    public String getHuge() {
        return huge;
    }

    /**
     * @param huge the huge to set
     */
    public void setHuge(String huge) {
        this.huge = huge;
    }

}

进入我src/test/resourcesapplication.properties文件:

files.huge: /home/jcabre/Downloads/1GB.zip

有任何想法吗?

编辑

主要的 Spring 引导应用程序:

@SpringBootApplication(
    //scanBasePackages = { "cat.gencat.ctti.canigo.arch.web.rs" },
    exclude = JmxAutoConfiguration.class
)
@EnableConfigurationProperties({
    ApiProperties.class,
    FileStoreProperties.class
})
@Import(RedisConfiguration.class)
public class ApiApplication {

    public static void main(String[] args) {
        SpringApplication.run(ApiApplication.class, args);
    }
}

标签: spring-bootspring-boot-test

解决方案


TL;博士:

它正在发生,因为@ConfigurationProperties它们不是由您在测试中构建的应用程序上下文管理的,尽管它们将在应用程序启动时加载,因为您@EnableConfigurationProperties在应用程序主类上有。

@EnableConfigurationPropertieson main class 只会影响你在的应用程序上下文bootRun但不会 @SpringBootTest影响. 在许多情况下,您在测试中构建的应用程序上下文可能与 的应用程序上下文不同bootRun,就像您的情况一样。

您可以在 in和 in 中添加@Component以使上下文知道它。这是最简单的方法,但不是 100% 建议的方法。gradle bootRungradle test


如果你有时间,更合适的方法与细节

相反,您可以添加@EnableConfigurationProperties({Config1.class, Config2.class})一个@SpringBootTest, 以仅将一些配置属性类注入到上下文中,以避免注入开销。

就像:

//@RunWith(SpringRunner.class) // for JUnit4 in Spring
@ExtendWith(SpringExtension.class) // for JUnit5 in Spring. 
@SpringBootTest
@EnableConfigurationProperties({
        ResourcesConfigProperties.class,
})
@Data
public class ConfigsTest {

    @Autowired
    private ResourcesConfigProperties resourceConfigProperties;

    ...

}

更好的是,您可以使用@SpringBootTest(classes={}): 类{}是您希望应用程序上下文@SpringBootTest管理的那些(创建、初始化、从 yaml 文件加载属性等)。然后您不必加载所有上下文,而只需加载其中的一部分。

您可以将 的所有类分组@ConfigurationProperties到一个类中@Configuration,并将其放在classes={}@SpringBootTest,而不是在任何地方重复这个列表@ConfigurationProperties。就像是:

//@RunWith(SpringRunner.class) // for JUnit4 in Spring
@ExtendWith(SpringExtension.class) // for JUnit5 in Spring. 
@SpringBootTest(classes = {
    TestConfiguration.class
})
@Data
public class ConfigsTest {

    @Autowired
    private ResourcesConfigProperties resourceConfigProperties;


    ...

}

TestConfiguration.java

@EnableConfigurationProperties({
        ResourcesConfigProperties.class,
})
@Configuration
public class TestConfiguration {
}

推荐阅读