Spring boot:@ConfigurationProperties 对测试不满意

Jor*_*rdi 3 spring-boot spring-boot-test

我在测试执行中遇到此异常:

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"
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

并且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;
    }

}
Run Code Online (Sandbox Code Playgroud)

进入我的src/test/resources我有我的application.properties文件:

files.huge: /home/jcabre/Downloads/1GB.zip
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?

编辑

主要的 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

Wes*_*Gun 10

特尔;博士:

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

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

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


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

相反,你可以添加@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;

    ...

}
Run Code Online (Sandbox Code Playgroud)

更好的是,您可以使用@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;


    ...

}
Run Code Online (Sandbox Code Playgroud)

TestConfiguration.java

@EnableConfigurationProperties({
        ResourcesConfigProperties.class,
})
@Configuration
public class TestConfiguration {
}
Run Code Online (Sandbox Code Playgroud)


Pra*_*ami -2

您还需要使用以下注释ResourcesConfigProperties@Configuration,否则它不会在spring容器中创建该类的bean。

@Configuration
@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;
    }

}
Run Code Online (Sandbox Code Playgroud)