Github地址html
@TestConfiguration是Spring Boot Test提供的一種工具,用它咱們能夠在通常的@Configuration以外補充測試專門用的Bean或者自定義的配置。java
@TestConfiguration其實是一種@TestComponent,@TestComponent是另外一種@Component,在語義上用來指定某個Bean是專門用於測試的。git
須要特別注意,你應該使用一切辦法避免在生產代碼中自動掃描到@TestComponent。
若是你使用@SpringBootApplication
啓動測試或者生產代碼,@TestComponent會自動被排除掉,若是不是則須要像@SpringBootApplication
同樣添加TypeExcludeFilter
:github
//... @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), // ...}) public @interface SpringBootApplication
@TestConfiguration和@Configuration不一樣,它不會阻止@SpringBootTest去查找機制(在Chapter 1: 基本用法 - 使用Spring Boot Testing工具 - 例子4提到過),正如@TestConfiguration的javadoc所說,它只是對既有配置的一個補充。spring
因此咱們在測試代碼上添加@SpringBootConfiguration,用@SpringBootTest(classes=...)
或者在同package裏添加@SpringBootConfiguration類都是能夠的。api
並且@TestConfiguration做爲內部類的時候它是會被@SpringBootTest掃描掉的,這點和@Configuration同樣。app
測試代碼TestConfigurationTest:spring-boot
@SpringBootTest @SpringBootConfiguration public class TestConfigurationTest extends AbstractTestNGSpringContextTests { @Autowired private Foo foo; @Test public void testPlusCount() throws Exception { assertEquals(foo.getName(), "from test config"); } @TestConfiguration public class TestConfig { @Bean public Foo foo() { return new Foo("from test config"); } } }
@TestConfiguration可以:工具
補充額外的Bean測試
覆蓋已存在的Bean
要特別注意第二點,@TestConfiguration可以直接覆蓋已存在的Bean,這一點正常的@Configuration是作不到的。
咱們先提供了一個正常的@Configuration(Config):
@Configuration public class Config { @Bean public Foo foo() { return new Foo("from config"); } }
又提供了一個@TestConfiguration,在裏面覆蓋了foo
Bean,而且提供了foo2
Bean(TestConfig):
@TestConfiguration public class TestConfig { // 這裏不須要@Primary之類的機制,直接就可以覆蓋 @Bean public Foo foo() { return new Foo("from test config"); } @Bean public Foo foo2() { return new Foo("from test config2"); } }
@SpringBootTest(classes = { Config.class, TestConfig.class }) public class TestConfigurationTest extends AbstractTestNGSpringContextTests { @Qualifier("foo") @Autowired private Foo foo; @Qualifier("foo2") @Autowired private Foo foo2; @Test public void testPlusCount() throws Exception { assertEquals(foo.getName(), "from test config"); assertEquals(foo2.getName(), "from test config2"); } }
再查看輸出的日誌,就會發現Auto Configuration已經關閉。
在上面的這個例子裏的TestConfig是會被@ComponentScan掃描到的,若是要避免被掃描到,在本文開頭已經提到過了。
先來看一下沒有作任何過濾的情形,咱們先提供了一個@SpringBootConfiguration(IncludeConfig):
@SpringBootConfiguration @ComponentScan public interface IncludeConfig { }
而後有個測試代碼引用了它(TestConfigIncludedTest):
@SpringBootTest(classes = IncludeConfig.class) public class TestConfigIncludedTest extends AbstractTestNGSpringContextTests { @Autowired(required = false) private TestConfig testConfig; @Test public void testPlusCount() throws Exception { assertNotNull(testConfig); } }
從這段代碼能夠看到TestConfig
被加載了。
如今咱們使用TypeExcludeFilter來過濾@TestConfiguration(ExcludeConfig1):
@SpringBootConfiguration @ComponentScan(excludeFilters = { @ComponentScan.Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class) }) public interface ExcludeConfig1 { }
再來看看結果(TestConfigExclude_1_Test):
@SpringBootTest(classes = ExcludeConfig1.class) public class TestConfigExclude_1_Test extends AbstractTestNGSpringContextTests { @Autowired(required = false) private TestConfig testConfig; @Test public void test() throws Exception { assertNull(testConfig); } }
還能夠用@SpringBootApplication來排除TestConfig
(ExcludeConfig2):
@SpringBootApplication public interface ExcludeConfig2 { }
看看結果(TestConfigExclude_2_Test):
@SpringBootTest(classes = ExcludeConfig2.class) public class TestConfigExclude_2_Test extends AbstractTestNGSpringContextTests { @Autowired(required = false) private TestConfig testConfig; @Test public void testPlusCount() throws Exception { assertNull(testConfig); } }