Java 如何在 Spring Boot JUnit 测试中排除 *AutoConfiguration 类?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26698071/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to exclude *AutoConfiguration classes in Spring Boot JUnit tests?
提问by Hendy Irawan
I tried:
我试过:
@RunWith(SpringJUnit4ClassRunner.class)
@EnableAutoConfiguration(exclude=CrshAutoConfiguration.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebAppConfiguration
public class LikeControllerTest {
However the CRaSSHD still starts up. While currently it doesn't harm the test, I'd like to disable unnecessary modules during unit testing to speed up and also avoid potential conflicts.
但是 CRaSSHD 仍然启动。虽然目前它不会损害测试,但我想在单元测试期间禁用不必要的模块以加快速度并避免潜在的冲突。
采纳答案by coderatchet
Top answers don't point to an even simpler and more flexible solution.
最佳答案并不指向更简单、更灵活的解决方案。
just place a
只需放置一个
@TestPropertySource(properties=
{"spring.autoconfigure.exclude=comma.seperated.ClassNames,com.example.FooAutoConfiguration"})
@SpringBootTest
public class MySpringTest {...}
annotation above your test class. This means other tests aren't affected by the current test's special case. If there is a configuration affecting most of your tests, then consider using the spring profile instead as the current top answer suggests.
测试类上方的注释。这意味着其他测试不受当前测试的特殊情况影响。如果存在影响大多数测试的配置,请考虑使用 spring 配置文件,如当前最佳答案所建议的那样。
Thanks to @skirsch for encouraging me to upgrade this from a comment to an answer.
感谢@skirsch 鼓励我将其从评论升级为答案。
回答by Jean-Philippe Bond
I think that using the @EnableAutoConfiguration
annotation on a test class won't work if you are using @SpringApplicationConfiguration
to load your Application
class. The thing is that you already have a @EnableAutoConfiguration
annotation in the Application
class that does not exclude the CrshAutoConfiguration
.Spring
uses that annotation instead of the one on your test class to do the auto configuration of your beans.
我认为,@EnableAutoConfiguration
如果您使用的@SpringApplicationConfiguration
是加载类,则在测试类上使用注释将不起作用Application
。问题是您@EnableAutoConfiguration
在Application
类中已经有一个不排除CrshAutoConfiguration
. Spring
使用该注释而不是测试类上的注释来自动配置 bean。
I think that your best bet is to use a different application context for your tests and exclude the CrshAutoConfiguration
in that class.
我认为您最好的选择是为您的测试使用不同的应用程序上下文并排除CrshAutoConfiguration
该类中的 。
I did some tests and it seems that @EnableAutoConfiguration
on the test class is completely ignore if you are using the @SpringApplicationConfiguration
annotation and the SpringJUnit4ClassRunner
.
我做了一些测试,@EnableAutoConfiguration
如果您使用@SpringApplicationConfiguration
注释和SpringJUnit4ClassRunner
.
回答by Matt C
I had a similar use case where I wanted to test a Spring Boot configured repository in isolation (in my case without Spring Security autoconfiguration which was failing my test). @SpringApplicationConfiguration
uses SpringApplicationContextLoader
and that has a JavaDoc stating
我有一个类似的用例,我想单独测试 Spring Boot 配置的存储库(在我的情况下,没有 Spring Security 自动配置,我的测试失败了)。@SpringApplicationConfiguration
使用SpringApplicationContextLoader
并且有一个 JavaDoc 说明
Can be used to test non-web features (like a repository layer) or start an fully-configured embedded servlet container.
可用于测试非 Web 功能(如存储库层)或启动完全配置的嵌入式 servlet 容器。
However, like yourself, I could not work out how you are meant to configure the test to only test the repository layer using the main configuration entry point i.e. using your approach of @SpringApplicationConfiguration(classes = Application.class)
.
但是,像您一样,我无法弄清楚您打算如何将测试配置为仅使用主配置入口点测试存储库层,即使用您的@SpringApplicationConfiguration(classes = Application.class)
.
My solution was to create a completely new application context exclusive for testing. So in src/test/java I have two files in a sub-package called repo
我的解决方案是为测试创建一个全新的应用程序上下文。所以在 src/test/java 中,我在名为 repo 的子包中有两个文件
RepoIntegrationTest.java
TestRepoConfig.java
RepoIntegrationTest.java
TestRepoConfig.java
where RepoIntegrationTest.java
has
哪里RepoIntegrationTest.java
有
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = TestRepoConfig.class)
public class RepoIntegrationTest {
and TestRepoConfig.java
has
并且TestRepoConfig.java
有
@SpringBootApplication(exclude = SecurityAutoConfiguration.class)
public class TestRepoConfig {
It got me out of trouble but it would be really useful if anyone from the Spring Boot team could provide an alternative recommended solution
它让我摆脱了麻烦,但如果 Spring Boot 团队中的任何人都可以提供替代的推荐解决方案,那将非常有用
回答by myroch
got into same kind of problem, wasn't able to exclude main spring boot class during testing. Solved it using following approach.
遇到了同样的问题,在测试期间无法排除主要的 spring 引导类。使用以下方法解决了它。
Instead of using @SpringBootApplication, use all three annotations which it contains and assign the name to @Configuration
不要使用@SpringBootApplication,而是使用它包含的所有三个注释并将名称分配给@Configuration
@Configuration("myApp")
@EnableAutoConfiguration
@ComponentScan
public class MyApp { .. }
In your test class define configuration with exactly same name:
在您的测试类中定义具有完全相同名称的配置:
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
// ugly hack how to exclude main configuration
@Configuration("myApp")
@SpringApplicationConfiguration(classes = MyTest.class)
public class MyTest { ... }
This should help. Would be nice to have some better way in place how to disable auto scanning for configuration annotations...
这应该有帮助。如果有一些更好的方法来禁用配置注释的自动扫描,那就太好了……
回答by Eddie B
I struggled with this as well and found a simple pattern to isolate the test context after a cursory read of the @ComponentScandocs.
我也为此苦苦挣扎,并在粗略阅读了@ComponentScan文档后找到了一个简单的模式来隔离测试上下文。
/**
* Type-safe alternative to {@link #basePackages} for specifying the packages
* to scan for annotated components. The package of each class specified will be scanned.
* Consider creating a special no-op marker class or interface in each package
* that serves no purpose other than being referenced by this attribute.
*/Class<?>[] basePackageClasses() default {};
/**
* {@link #basePackages} 的类型安全替代方案,用于指定包
* 以扫描带注释的组件。将扫描指定的每个类的包。
*考虑在每个包中创建一个特殊的无操作标记类或接口
*除了被此属性引用外,没有其他用途。
*/Class<?>[] basePackageClasses() default {};
- Create a package for your spring tests,
("com.example.test")
. - Create a marker interface in the package as a context qualifier.
- Provide the marker interface reference as a parameter to basePackageClasses.
- 为您的弹簧测试创建一个包,
("com.example.test")
. - 在包中创建一个标记接口作为上下文限定符。
- 将标记接口引用作为参数提供给 basePackageClasses。
Example
例子
IsolatedTest.java
IsolatedTest.java
package com.example.test;
@RunWith(SpringJUnit4ClassRunner.class)
@ComponentScan(basePackageClasses = {TestDomain.class})
@SpringApplicationConfiguration(classes = IsolatedTest.Config.class)
public class IsolatedTest {
String expected = "Read the documentation on @ComponentScan";
String actual = "Too lazy when I can just search on Stack Overflow.";
@Test
public void testSomething() throws Exception {
assertEquals(expected, actual);
}
@ComponentScan(basePackageClasses = {TestDomain.class})
public static class Config {
public static void main(String[] args) {
SpringApplication.run(Config.class, args);
}
}
}
...
TestDomain.java
TestDomain.java
package com.example.test;
public interface TestDomain {
//noop marker
}
回答by Stuart
I had a similar problem but I came to a different solution that may help others. I used Spring Profiles to separate out test and app configuration classes.
我遇到了类似的问题,但我找到了可能对其他人有所帮助的不同解决方案。我使用 Spring Profiles 来分离测试和应用程序配置类。
Create a TestConfig class with a specific profile and exclude any app configuration from component scan you wish here.
In your test class set the profile to match the TestConfig and include it using the @ContextConfiguration annotation.
创建一个具有特定配置文件的 TestConfig 类,并从您希望的组件扫描中排除任何应用程序配置。
在您的测试类中,将配置文件设置为与 TestConfig 匹配并使用 @ContextConfiguration 注释将其包含在内。
For example:
例如:
configuration:
配置:
@Profile("test")
@Configuration
@EnableWebMvc
@ComponentScan(
basePackages="your.base.package",
excludeFilters = {
@Filter(type = ASSIGNABLE_TYPE,
value = {
ExcludedAppConfig1.class,
ExcludedAppConfig2.class
})
})
public class TestConfig { ...}
test:
测试:
@ActiveProfiles("test")
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = TestConfig.class)
@WebAppConfiguration
public class SomeTest{ ... }
回答by Kane
Another simple way to exclude the auto configuration classes,
另一种排除自动配置类的简单方法,
Add below similar configuration to your application.ymlfile,
将以下类似配置添加到您的application.yml文件中,
---
spring:
profiles: test
autoconfigure.exclude: org.springframework.boot.autoconfigure.session.SessionAutoConfiguration
回答by James McShane
With the new @SpringBootTest
annotation, I took this answerand modified it to use profiles with a @SpringBootApplication
configuration class. The @Profile
annotation is necessary so that this class is only picked up during the specific integration tests that need this, as other test configurations do different component scanning.
使用新@SpringBootTest
注释,我接受了这个答案并将其修改为使用带有@SpringBootApplication
配置类的配置文件。该@Profile
注释是必要的,这个类中需要这一点,因为其他的测试配置做不同的组件扫描特定的集成测试只拾起。
Here is the configuration class:
这是配置类:
@Profile("specific-profile")
@SpringBootApplication(scanBasePackages={"com.myco.package1", "com.myco.package2"})
public class SpecificTestConfig {
}
Then, the test class references this configuration class:
然后,测试类引用这个配置类:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = { SpecificTestConfig.class })
@ActiveProfiles({"specific-profile"})
public class MyTest {
}
回答by Tom Saleeba
If you're having this problem with Spring Boot 1.4.x and up, you might be able to use @OverrideAutoConfiguration(enabled=true)
to solve the problem.
如果您在使用 Spring Boot 1.4.x 及更高版本时遇到此问题,您或许可以使用它@OverrideAutoConfiguration(enabled=true)
来解决该问题。
Similar to what was asked/answered here https://stackoverflow.com/a/39253304/1410035
类似于这里询问/回答的内容https://stackoverflow.com/a/39253304/1410035
回答by Kingson wu
@SpringBootTest(classes = {Application.class}
, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT
, properties="spring.autoconfigure.exclude=com.xx.xx.AutoConfiguration"
)
ref:https://github.com/spring-projects/spring-boot/issues/8579
参考:https: //github.com/spring-projects/spring-boot/issues/8579
回答by Taugenichts
If the issue is that your SpringBootApplication/Configuration you are bringing in is component scanning the package your test configurations are in, you can actually remove the @Configuration annotation from the test configurations and you can still use them in the @SpringBootTest annotations. For example, if you have a class Application that is your main configuration and a class TestConfiguration that is a configuration for certain, but not all tests, you can set up your classes as follows:
如果问题是您引入的 SpringBootApplication/Configuration 是组件扫描您的测试配置所在的包,您实际上可以从测试配置中删除 @Configuration 注释,您仍然可以在 @SpringBootTest 注释中使用它们。例如,如果您有一个类 Application 是您的主要配置,而一个类 TestConfiguration 是某些但不是所有测试的配置,您可以按如下方式设置您的类:
@Import(Application.class) //or the specific configurations you want
//(Optional) Other Annotations that will not trigger an autowire
public class TestConfiguration {
//your custom test configuration
}
And then you can configure your tests in one of two ways:
然后您可以通过以下两种方式之一配置您的测试:
With the regular configuration:
@SpringBootTest(classes = {Application.class}) //won't component scan your configuration because it doesn't have an autowire-able annotation //Other annotations here public class TestThatUsesNormalApplication { //my test code }
With the test custom test configuration:
@SpringBootTest(classes = {TestConfiguration.class}) //this still works! //Other annotations here public class TestThatUsesCustomTestConfiguration { //my test code }
使用常规配置:
@SpringBootTest(classes = {Application.class}) //won't component scan your configuration because it doesn't have an autowire-able annotation //Other annotations here public class TestThatUsesNormalApplication { //my test code }
使用测试自定义测试配置:
@SpringBootTest(classes = {TestConfiguration.class}) //this still works! //Other annotations here public class TestThatUsesCustomTestConfiguration { //my test code }