摘要:地址前面一個部分講解了如何使用工具來測試項目,現(xiàn)在我們講解如何使用工具來測試項目。所以我們可以利用這個特性來進一步簡化測試代碼。因為只有這樣才能夠在測試環(huán)境下發(fā)現(xiàn)生產(chǎn)環(huán)境的問題,也避免出現(xiàn)一些因為配置不同導致的奇怪問題。
Github地址
前面一個部分講解了如何使用Spring Testing工具來測試Spring項目,現(xiàn)在我們講解如何使用Spring Boot Testing工具來測試Spring Boot項目。
例子1:直接加載Bean在Spring Boot項目里既可以使用Spring Boot Testing工具,也可以使用Spring Testing工具。
在Spring項目里,一般使用Spring Testing工具,雖然理論上也可以使用Spring Boot Testing,不過因為Spring Boot Testing工具會引入Spring Boot的一些特性比如AutoConfiguration,這可能會給你的測試帶來一些奇怪的問題,所以一般不推薦這樣做。
使用Spring Boot Testing工具只需要將@ContextConfiguration改成@SpringBootTest即可,源代碼見FooServiceImpltest:
@SpringBootTest(classes = FooServiceImpl.class) public class FooServiceImplTest extends AbstractTestNGSpringContextTests { @Autowired private FooService foo; @Test public void testPlusCount() throws Exception { assertEquals(foo.getCount(), 0); foo.plusCount(); assertEquals(foo.getCount(), 1); } }例子2:使用內(nèi)嵌@Configuration加載Bean
源代碼見FooServiceImpltest:
@SpringBootTest public class FooServiceImplTest extends AbstractTestNGSpringContextTests { @Autowired private FooService foo; @Test public void testPlusCount() throws Exception { assertEquals(foo.getCount(), 0); foo.plusCount(); assertEquals(foo.getCount(), 1); } @Configuration @Import(FooServiceImpl.class) static class Config { } }例子3:使用外部@Configuration加載Bean
Config:
@Configuration @Import(FooServiceImpl.class) public class Config { }
FooServiceImpltest:
@SpringBootTest(classes = Config.class) public class FooServiceImplTest extends AbstractTestNGSpringContextTests { @Autowired private FooService foo; @Test public void testPlusCount() throws Exception { assertEquals(foo.getCount(), 0); foo.plusCount(); assertEquals(foo.getCount(), 1); } }
這個例子和例子2差不多,只不過將@Configuration放到了外部。
例子4:使用@SpringBootConfiguration前面的例子@SpringBootTest的用法和@ContextConfiguration差不多。不過根據(jù)@SpringBootTest的文檔:
它會嘗試加載@SpringBootTest(classes=...)的定義的Annotated classes。Annotated classes的定義在ContextConfiguration中有說明。
如果沒有設定@SpringBootTest(classes=...),那么會去找當前測試類的nested @Configuration class
如果上一步找到,則會嘗試查找@SpringBootConfiguration,查找的路徑有:1)看當前測試類是否@SpringBootConfiguration,2)在當前測試類所在的package里找。
所以我們可以利用這個特性來進一步簡化測試代碼。
Config:
@SpringBootConfiguration @Import(FooServiceImpl.class) public class Config { }
FooServiceImpltest:
@SpringBootTest public class FooServiceImplTest extends AbstractTestNGSpringContextTests { @Autowired private FooService foo; @Test public void testPlusCount() throws Exception { assertEquals(foo.getCount(), 0); foo.plusCount(); assertEquals(foo.getCount(), 1); } }例子5:使用@ComponentScan掃描Bean
前面的例子我們都使用@Import來加載Bean,雖然這中方法很精確,但是在大型項目中很麻煩。
在常規(guī)的Spring Boot項目中,一般都是依靠自動掃描機制來加載Bean的,所以我們希望我們的測試代碼也能夠利用自動掃描機制來加載Bean。
Config:
@SpringBootConfiguration @ComponentScan(basePackages = "me.chanjar.basic.service") public class Config { }
FooServiceImpltest:
@SpringBootTest public class FooServiceImplTest extends AbstractTestNGSpringContextTests { @Autowired private FooService foo; @Test public void testPlusCount() throws Exception { assertEquals(foo.getCount(), 0); foo.plusCount(); assertEquals(foo.getCount(), 1); } }例子6:使用@SpringBootApplication
也可以在測試代碼上使用@SpringBootApplication,它有這么幾個好處:
自身SpringBootConfiguration
提供了@ComponentScan配置,以及默認的excludeFilter,有了這些filter Spring在初始化ApplicationContext的時候會排除掉某些Bean和@Configuration
啟用了EnableAutoConfiguration,這個特性能夠利用Spring Boot來自動化配置所需要的外部資源,比如數(shù)據(jù)庫、JMS什么的,這在集成測試的時候非常有用。
Config:
@SpringBootApplication(scanBasePackages = "me.chanjar.basic.service") public class Config { }
FooServiceImpltest:
@SpringBootTest public class FooServiceImplTest extends AbstractTestNGSpringContextTests { @Autowired private FooService foo; @Test public void testPlusCount() throws Exception { assertEquals(foo.getCount(), 0); foo.plusCount(); assertEquals(foo.getCount(), 1); } }避免@SpringBootConfiguration沖突
當@SpringBootTest沒有定義(classes=...,且沒有找到nested @Configuration class的情況下,會嘗試查詢@SpringBootConfiguration,如果找到多個的話則會拋出異常:
Caused by: java.lang.IllegalStateException: Found multiple @SpringBootConfiguration annotated classes [Generic bean: class [...]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in file [/Users/qianjia/workspace-os/spring-test-examples/basic/target/test-classes/me/chanjar/basic/springboot/ex7/FooServiceImplTest1.class], Generic bean: class [me.chanjar.basic.springboot.ex7.FooServiceImplTest2]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in file [...]]
比如以下代碼就會造成這個問題:
@SpringBootApplication(scanBasePackages = "me.chanjar.basic.service") public class Config1 { } @SpringBootApplication(scanBasePackages = "me.chanjar.basic.service") public class Config2 { } @SpringBootTest public class FooServiceImplTest extends AbstractTestNGSpringContextTests { // ... }
解決這個問題的方法有就是避免自動查詢@SpringBootConfiguration:
定義@SpringBootTest(classes=...)
提供nested @Configuration class
最佳實踐除了單元測試(不需要初始化ApplicationContext的測試)外,盡量將測試配置和生產(chǎn)配置保持一致。比如如果生產(chǎn)配置里啟用了AutoConfiguration,那么測試配置也應該啟用。因為只有這樣才能夠在測試環(huán)境下發(fā)現(xiàn)生產(chǎn)環(huán)境的問題,也避免出現(xiàn)一些因為配置不同導致的奇怪問題。
在測試代碼之間盡量做到配置共用,這么做的優(yōu)點有3個:
能夠有效利用Spring TestContext Framework的緩存機制,ApplicationContext只會創(chuàng)建一次,后面的測試會直接用已創(chuàng)建的那個,加快測試代碼運行速度。
當項目中的Bean很多的時候,這么做能夠降低測試代碼復雜度,想想如果每個測試代碼都有一套自己的@Configuration或其變體,那得多嚇人。
參考文檔Spring Framework Testing
Spring Boot Testing
Spring TestContext Framework
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/70260.html
摘要:地址提供了,能夠很方便的來測試。同時也提供了更進一步簡化了測試需要的配置工作。本章節(jié)將分別舉例說明在不使用和使用下如何對進行測試。例子測試的關鍵是使用對象,利用它我們能夠在不需啟動容器的情況下測試的行為。 Github地址 Spring Testing Framework提供了Spring MVC Test Framework,能夠很方便的來測試Controller。同時Spring...
摘要:地址是提供的方便測試序列化反序列化的測試工具,在的文檔中有一些介紹。例子簡單例子源代碼見使用通包下的文件測試結(jié)果是否正確或者使用基于的校驗例子測試可以用來測試。這個例子里使用了自定義的測試代碼例子使用事實上也可以配合一起使用。 Github地址 @JsonTest是Spring Boot提供的方便測試JSON序列化反序列化的測試工具,在Spring Boot的文檔中有一些介紹。 需要注...
摘要:因為只有這樣才能夠在測試環(huán)境下發(fā)現(xiàn)生產(chǎn)環(huán)境的問題,也避免出現(xiàn)一些因為配置不同導致的奇怪問題。而方法則能夠不改變原有配置不提供新的配置的情況下,就能夠關閉。 Github地址 在Chapter 1: 基本用法 - 使用Spring Boot Testing工具里提到: 除了單元測試(不需要初始化ApplicationContext的測試)外,盡量將測試配置和生產(chǎn)配置保持一致。比如如果生產(chǎn)...
Github地址 在Spring引入Java Config機制之后,我們會越來越多的使用@Configuration來注冊Bean,并且Spring Boot更廣泛地使用了這一機制,其提供的大量Auto Configuration大大簡化了配置工作。那么問題來了,如何確保@Configuration和Auto Configuration按照預期運行呢,是否正確地注冊了Bean呢?本章舉例測試@Co...
摘要:地址可以用來覆蓋掉來自于系統(tǒng)環(huán)境變量系統(tǒng)屬性的屬性。同時優(yōu)先級高于。利用它我們可以很方便的在測試代碼里微調(diào)模擬配置比如修改操作系統(tǒng)目錄分隔符數(shù)據(jù)源等。源代碼例子使用工具也可以和一起使用。源代碼見參考文檔 Github地址 @TestPropertySource可以用來覆蓋掉來自于系統(tǒng)環(huán)境變量、Java系統(tǒng)屬性、@PropertySource的屬性。 同時@TestPropertySou...
閱讀 2682·2021-11-16 11:53
閱讀 2745·2021-07-26 23:38
閱讀 2077·2019-08-30 15:55
閱讀 1758·2019-08-30 13:21
閱讀 3674·2019-08-29 17:26
閱讀 3313·2019-08-29 13:20
閱讀 882·2019-08-29 12:20
閱讀 3199·2019-08-26 10:21