Github地址
在Spring引入Java Config機(jī)制之后,我們會(huì)越來越多的使用@Configuration來注冊(cè)Bean,并且Spring Boot更廣泛地使用了這一機(jī)制,其提供的大量Auto Configuration大大簡化了配置工作。那么問題來了,如何確保@Configuration和Auto Configuration按照預(yù)期運(yùn)行呢,是否正確地注冊(cè)了Bean呢?本章舉例測試@Configuration和Auto Configuration的方法(因?yàn)锳uto Configuration也是@Configuration,所以測試方法是一樣的)。
例子1:測試@Configuration我們先寫一個(gè)簡單的@Configuration:
@Configuration public class FooConfiguration { @Bean public Foo foo() { return new Foo(); } }
然后看FooConfiguration是否能夠正確地注冊(cè)Bean:
public class FooConfigurationTest { private AnnotationConfigApplicationContext context; @BeforeMethod public void init() { context = new AnnotationConfigApplicationContext(); } @AfterMethod(alwaysRun = true) public void reset() { context.close(); } @Test public void testFooCreation() { context.register(FooConfiguration.class); context.refresh(); assertNotNull(context.getBean(Foo.class)); } }
注意上面代碼中關(guān)于Context的代碼:
首先,我們構(gòu)造一個(gè)Context
然后,注冊(cè)FooConfiguration
然后,refresh Context
最后,在測試方法結(jié)尾close Context
如果你看Spring Boot中關(guān)于@Configuration測試的源代碼會(huì)發(fā)現(xiàn)和上面的代碼有點(diǎn)不一樣:
public class DataSourceAutoConfigurationTests { private final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); @Before public void init() { EmbeddedDatabaseConnection.override = null; EnvironmentTestUtils.addEnvironment(this.context, "spring.datasource.initialize:false", "spring.datasource.url:jdbc:hsqldb:mem:testdb-" + new Random().nextInt()); } @After public void restore() { EmbeddedDatabaseConnection.override = null; this.context.close(); }
這是因?yàn)镾pring和Spring Boot都是用JUnit做測試的,而JUnit的特性是每次執(zhí)行測試方法前,都會(huì)new一個(gè)測試類實(shí)例,而TestNG是在共享同一個(gè)測試類實(shí)例的。
例子2:測試@ConditionalSpring Framework提供了一種可以條件控制@Configuration的機(jī)制,即只在滿足某條件的情況下才會(huì)導(dǎo)入@Configuration,這就是@Conditional。
下面我們來對(duì)@Conditional做一些測試,首先我們自定義一個(gè)Condition FooConfiguration:
@Configuration public class FooConfiguration { @Bean @Conditional(FooCondition.class) public Foo foo() { return new Foo(); } public static class FooCondition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { if (context.getEnvironment() != null) { Boolean property = context.getEnvironment().getProperty("foo.create", Boolean.class); return Boolean.TRUE.equals(property); } return false; } } }
該Condition判斷Environment中是否有foo.create=true。
如果我們要測試這個(gè)Condition,那么就必須往Environment里添加相關(guān)property才可以,在這里我們測試了三種情況:
沒有配置foo.create=true
配置foo.create=true
配置foo.create=false
FooConfigurationTest:
public class FooConfigurationTest { private AnnotationConfigApplicationContext context; @BeforeMethod public void init() { context = new AnnotationConfigApplicationContext(); } @AfterMethod(alwaysRun = true) public void reset() { context.close(); } @Test(expectedExceptions = NoSuchBeanDefinitionException.class) public void testFooCreatePropertyNull() { context.register(FooConfiguration.class); context.refresh(); context.getBean(Foo.class); } @Test public void testFooCreatePropertyTrue() { context.getEnvironment().getPropertySources().addLast( new MapPropertySource("test", Collections.singletonMap("foo.create", "true")) ); context.register(FooConfiguration.class); context.refresh(); assertNotNull(context.getBean(Foo.class)); } @Test(expectedExceptions = NoSuchBeanDefinitionException.class) public void testFooCreatePropertyFalse() { context.getEnvironment().getPropertySources().addLast( new MapPropertySource("test", Collections.singletonMap("foo.create", "false")) ); context.register(FooConfiguration.class); context.refresh(); assertNotNull(context.getBean(Foo.class)); } }
注意我們用以下方法來給Environment添加property:
context.getEnvironment().getPropertySources().addLast( new MapPropertySource("test", Collections.singletonMap("foo.create", "true")) );
所以針對(duì)@Conditional和其對(duì)應(yīng)的Condition的測試的根本就是給它不一樣的條件,判斷其行為是否正確,在這個(gè)例子里我們的Condition比較簡單,只是判斷是否存在某個(gè)property,如果復(fù)雜Condition的話,測試思路也是一樣的。
例子3:測試@ConditionalOnPropertySpring framework只提供了@Conditional,Spring boot對(duì)這個(gè)機(jī)制做了擴(kuò)展,提供了更為豐富的@ConditionalOn*,這里我們以@ConditionalOnProperty舉例說明。
先看FooConfiguration:
@Configuration public class FooConfiguration { @Bean @ConditionalOnProperty(prefix = "foo", name = "create", havingValue = "true") public Foo foo() { return new Foo(); } }
FooConfigurationTest:
public class FooConfigurationTest { private AnnotationConfigApplicationContext context; @BeforeMethod public void init() { context = new AnnotationConfigApplicationContext(); } @AfterMethod(alwaysRun = true) public void reset() { context.close(); } @Test(expectedExceptions = NoSuchBeanDefinitionException.class) public void testFooCreatePropertyNull() { context.register(FooConfiguration.class); context.refresh(); context.getBean(Foo.class); } @Test public void testFooCreatePropertyTrue() { EnvironmentTestUtils.addEnvironment(context, "foo.create=true"); context.register(FooConfiguration.class); context.refresh(); assertNotNull(context.getBean(Foo.class)); } @Test(expectedExceptions = NoSuchBeanDefinitionException.class) public void testFooCreatePropertyFalse() { EnvironmentTestUtils.addEnvironment(context, "foo.create=false"); context.register(FooConfiguration.class); context.refresh(); assertNotNull(context.getBean(Foo.class)); } }
這段測試代碼和例子2的邏輯差不多,只不過例子2里使用了我們自己寫的Condition,這里使用了Spring Boot提供的@ConditionalOnProperty。
并且利用了Spring Boot提供的EnvironmentTestUtils簡化了給Environment添加property的工作:
EnvironmentTestUtils.addEnvironment(context, "foo.create=false");例子4:測試Configuration Properties
Spring Boot還提供了類型安全的Configuration Properties,下面舉例如何對(duì)其進(jìn)行測試。
BarConfiguration:
@Configuration @EnableConfigurationProperties(BarConfiguration.BarProperties.class) public class BarConfiguration { @Autowired private BarProperties barProperties; @Bean public Bar bar() { return new Bar(barProperties.getName()); } @ConfigurationProperties("bar") public static class BarProperties { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } }
BarConfigurationTest:
public class BarConfigurationTest { private AnnotationConfigApplicationContext context; @BeforeMethod public void init() { context = new AnnotationConfigApplicationContext(); } @AfterMethod(alwaysRun = true) public void reset() { context.close(); } @Test public void testBarCreation() { EnvironmentTestUtils.addEnvironment(context, "bar.name=test"); context.register(BarConfiguration.class, PropertyPlaceholderAutoConfiguration.class); context.refresh(); assertEquals(context.getBean(Bar.class).getName(), "test"); } }
注意到因?yàn)槲覀兪褂昧薈onfiguration Properties機(jī)制,需要注冊(cè)PropertyPlaceholderAutoConfiguration,否則在BarConfiguration里無法注入BarProperties。
參考文檔Conditionally include @Configuration classes or @Bean methods
Condition annotations
Type-safe Configuration Properties
Spring Framework Testing
Spring Boot Testing
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/70351.html
摘要:因?yàn)橹挥羞@樣才能夠在測試環(huán)境下發(fā)現(xiàn)生產(chǎn)環(huán)境的問題,也避免出現(xiàn)一些因?yàn)榕渲貌煌瑢?dǎo)致的奇怪問題。而方法則能夠不改變?cè)信渲貌惶峁┬碌呐渲玫那闆r下,就能夠關(guān)閉。 Github地址 在Chapter 1: 基本用法 - 使用Spring Boot Testing工具里提到: 除了單元測試(不需要初始化ApplicationContext的測試)外,盡量將測試配置和生產(chǎn)配置保持一致。比如如果生產(chǎn)...
摘要:源代碼見需要注意的是,如果是專供某個(gè)測試類使用的話,把它放到外部并不是一個(gè)好主意,因?yàn)樗锌赡軙?huì)被掃描到,從而產(chǎn)生一些奇怪的問題。 Github地址 既然我們現(xiàn)在開發(fā)的是一個(gè)Spring項(xiàng)目,那么肯定會(huì)用到Spring Framework的各種特性,這些特性實(shí)在是太好用了,它能夠大大提高我們的開發(fā)效率。那么自然而然,你會(huì)想在測試代碼里也能夠利用Spring Framework提供的特...
摘要:地址前面一個(gè)部分講解了如何使用工具來測試項(xiàng)目,現(xiàn)在我們講解如何使用工具來測試項(xiàng)目。所以我們可以利用這個(gè)特性來進(jìn)一步簡化測試代碼。因?yàn)橹挥羞@樣才能夠在測試環(huán)境下發(fā)現(xiàn)生產(chǎn)環(huán)境的問題,也避免出現(xiàn)一些因?yàn)榕渲貌煌瑢?dǎo)致的奇怪問題。 Github地址 前面一個(gè)部分講解了如何使用Spring Testing工具來測試Spring項(xiàng)目,現(xiàn)在我們講解如何使用Spring Boot Testing工具來測...
摘要:地址在使用工具中提到在測試代碼之間盡量做到配置共用。本章將列舉幾種共享測試配置的方法我們可以將測試配置放在一個(gè)里,然后在測試或中引用它。也可以利用的及自定義機(jī)制,提供自己的用在測試配置上。 Github地址 在使用Spring Boot Testing工具中提到: 在測試代碼之間盡量做到配置共用。...能夠有效利用Spring TestContext Framework的緩存機(jī)制,Ap...
摘要:地址是提供的一種工具,用它我們可以在一般的之外補(bǔ)充測試專門用的或者自定義的配置。實(shí)際上是一種,是另一種,在語義上用來指定某個(gè)是專門用于測試的。所以我們?cè)跍y試代碼上添加,用或者在同里添加類都是可以的。 Github地址 @TestConfiguration是Spring Boot Test提供的一種工具,用它我們可以在一般的@Configuration之外補(bǔ)充測試專門用的Bean或者自定...
閱讀 2491·2023-04-25 19:27
閱讀 3569·2021-11-24 09:39
閱讀 3983·2021-10-08 10:17
閱讀 3459·2019-08-30 13:48
閱讀 2010·2019-08-29 12:26
閱讀 3183·2019-08-28 17:52
閱讀 3596·2019-08-26 14:01
閱讀 3595·2019-08-26 12:19