javascript
boot spring test 文档_Spring、Spring Boot 和 TestNG 测试指南 ( 3 )
原標題:Spring、Spring Boot 和 TestNG 測試指南 ( 3 )
來源:chanjarster,
github.com/chanjarster/spring-test-examples
Spring&Spring Boot Testing工具提供了一些方便測試的Annotation,本文會對其中的一些做一些講解。
@TestPropertySource
@TestPropertySource可以用來覆蓋掉來自于系統環境變量,Java的系統屬性,@PropertySource的屬性。
同時@TestPropertySource(properties=…)優先級高于@TestPropertySource(locations=…)。
利用它我們可以很方便的在測試代碼里微調,模擬配置(比如修改操作系統目錄分隔符,數據源等)。
例子1:使用Spring Testing工具
我們先使用@PropertySource將一個外部屬性文件加載進來,PropertySourceConfig:
@Configuration
@PropertySource(“ classpath:me / chanjar / annotation / testps / ex1 / property-source.properties ”)
public class PropertySourceConfig {
}
file: property-source.properties
foo=abc
然后我們用@TestPropertySource覆蓋了這個特性:
TestPropertySource(properties = { “ foo = xyz ” ...
最后我們測試了是否覆蓋成功(結果是成功的):
@Test
public void testOverridePropertySource(){
的assertEquals(環境。的getProperty( “ FOO ”), “ XYZ ”);
}
同時我們還對@TestPropertySource做了一些其他的測試,具體情況你可以自己觀察。為了方便你觀察@TestPropertySource對系統環境變量和Java的系統屬性的覆蓋效果,我們在一開始打印出了它們的值。
源代碼TestPropertyTest:
@ContextConfiguration(類 = PropertySourceConfig 。類)
@TestPropertySource(
屬性 = { “富= XYZ ”,“巴= UVW ”,“ PATH = AAA ”,“ java.runtime.name = BBB ” },
位置 = “類路徑:我/chanjar/annotation/testps/ex1/test-property-source.properties “
)
公共 類 TestPropertyTest 擴展 AbstractTestNGSpringContextTests 實現 EnvironmentAware {
私人 環境環境;
@覆蓋
公共 無效 setEnvironment(環境 環境){
此。環境=環境;
Map < String,Object > systemEnvironment =((ConfigurableEnvironment)環境)。getSystemEnvironment();
系統。出去。println(“ ===系統環境=== ”);
系統。出去。的println(getMapString(systemEnvironment));
系統。出去。的println();
系統。出去。println(“ === Java系統屬性=== ”);
Map < String,Object > systemProperties =((ConfigurableEnvironment)環境)。getSystemProperties();
系統。出去。的println(getMapString(systemProperties));
}
@Test
public void testOverridePropertySource(){
的assertEquals(環境。的getProperty( “ FOO ”), “ XYZ ”);
}
@Test
public void testOverrideSystemEnvironment(){
的assertEquals(環境。的getProperty( “ PATH ”), “ AAA ”);
}
@Test
public void testOverrideJavaSystemProperties(){
的assertEquals(環境。的getProperty( “ java.runtime.name ”), “ BBB ”);
}
@Test
public void testInlineTestPropertyOverrideResourceLocationTestProperty(){
的assertEquals(環境。的getProperty( “條”), “ UVW ”);
}
private String getMapString(Map < String,Object > map){
return String 。加入(“ n ”,
地圖。keySet()。stream()。地圖(K - > ? + “ = ” +地圖。得到(k))的。收集(toList())
);
}
}
例子2:使用Spring Boot Testing工具
@TestPropertySource也可以和@SpringBootTest一起使用。
源代碼見TestPropertyTest:
@SpringBootTest(類 = PropertySourceConfig 。類)
@TestPropertySource(
屬性 = { “富= XYZ ”,“巴= UVW ”,“ PATH = AAA ”,“ java.runtime.name = BBB ” },
位置 = “類路徑:我/chanjar/annotation/testps/ex1/test-property-source.properties “
)
公共 類 TestPropertyTest 擴展 AbstractTestNGSpringContextTests 實現 EnvironmentAware {
// ..
@ActiveProfiles
@ActiveProfiles可以用來在測試的時候啟用某些資料的豆本章節的測試代碼使用了下面的這個配置:
@Configuration
public class Config {
@Bean
@Profile(“ dev ”)
public Foo fooDev(){
return new Foo(“ dev ”);
}
@Bean
@Profile(“ product ”)
public Foo fooProduct(){
return new Foo(“ product ”);
}
@Bean
@Profile(“ default ”)
public Foo fooDefault(){
return new Foo(“ default ”);
}
@Bean
public bar bar(){
return new bar(“ no profile ”);
}
}
例子1:不使用ActiveProfiles
在沒有@ActiveProfiles的時候,外形=默認和沒有設定個人資料的豆會被加載到。
源代碼ActiveProfileTest:
@ContextConfiguration(類 = 配置。類)
公共 類 ActiveProfileTest 延伸 AbstractTestNGSpringContextTests {
@Autowired
私人 Foo foo;
@Autowired
私人 酒吧 ;
@Test
public void test(){
的assertEquals(FOO 。的getName(), “默認”);
的assertEquals(巴。的getName(), “無簡檔”);
}
}
例子二:使用ActiveProfiles
當使用了@ActiveProfiles的時候,輪廓匹配的和沒有設定個人資料的豆會被加載到。
源代碼ActiveProfileTest:
@ContextConfiguration(類 = 配置。類)
[ @ActiveProfiles] [doc-active-profiles](“ product ”)
public class ActiveProfileTest extends AbstractTestNGSpringContextTests {
@Autowired
私人 Foo foo;
@Autowired
私人 酒吧 ;
@Test
public void test(){
的assertEquals(FOO 。的getName(), “產品”);
的assertEquals(巴。的getName(), “無簡檔”);
}
}
總結
在沒有@ActiveProfiles的時候,外形=默認和沒有設定個人資料的豆會被加載到。
當使用了@ActiveProfiles的時候,輪廓匹配的和沒有設定個人資料的豆會被加載到。
@ActiveProfiles同樣也可以和@SpringBootTest配合使用,這里就不舉例說明了。
@JsonTest
@JsonTest是Spring Boot提供的方便測試JSON序列化反序列化的測試工具,在Spring Boot的文檔中有一些介紹。
需要注意的是@JsonTest需要Jackson的ObjectMapper,事實上如果你的Spring Boot項目添加了spring-web的Maven依賴,JacksonAutoConfiguration就會自動為你配置一個:
org.springframework.boot
spring-boot-autoconfigure
org.springframework
spring-web
這里沒有提供關于日期時間的例子,關于這個比較復雜,可以看我的另一篇文章:Spring Boot Jackson對于日期時間類型處理的例子。
https://github.com/chanjarster/springboot-jackson-datetime-example
例子1:簡單例子
源代碼見SimpleJsonTest:
@SpringBootTest(classes = SimpleJsonTest.class)
@JsonTest
public class SimpleJsonTest extends AbstractTestNGSpringContextTests {
@Autowired
private JacksonTester json;
@Test
public void testSerialize() throws Exception {
Foo details = new Foo("Honda", 12);
// 使用通包下的json文件測試結果是否正確
assertThat(this.json.write(details)).isEqualToJson("expected.json");
// 或者使用基于JSON path的校驗
assertThat(this.json.write(details)).hasJsonPathStringValue("@.name");
assertThat(this.json.write(details)).extractingJsonPathStringValue("@.name").isEqualTo("Honda");
assertThat(this.json.write(details)).hasJsonPathNumberValue("@.age");
assertThat(this.json.write(details)).extractingJsonPathNumberValue("@.age").isEqualTo(12);
}
@Test
public void testDeserialize() throws Exception {
String content = "{"name":"Ford","age":13}";
Foo actual = this.json.parseObject(content);
assertThat(actual).isEqualTo(new Foo("Ford", 13));
assertThat(actual.getName()).isEqualTo("Ford");
assertThat(actual.getAge()).isEqualTo(13);
}
}
例子2: 測試@JsonComponent
@JsonTest可以用來測試@JsonComponent。
這個例子里使用了自定義的@JsonComponent FooJsonComponent:
@JsonComponent
public class FooJsonComponent {
public static class Serializer extends JsonSerializer {
@Override
public void serialize(Foo value, JsonGenerator gen, SerializerProvider serializers)
throws IOException, JsonProcessingException {
// ...
}
}
public static class Deserializer extends JsonDeserializer {
@Override
public Foo deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
// ...
}
}
}
測試代碼JsonComponentJsonTest:
@SpringBootTest(classes = { JsonComponentJacksonTest.class, FooJsonComponent.class })
@JsonTest
public class JsonComponentJacksonTest extends AbstractTestNGSpringContextTests {
@Autowired
private JacksonTester json;
@Test
public void testSerialize() throws Exception {
Foo details = new Foo("Honda", 12);
assertThat(this.json.write(details).getJson()).isEqualTo(""name=Honda,age=12"");
}
@Test
public void testDeserialize() throws Exception {
String content = ""name=Ford,age=13"";
Foo actual = this.json.parseObject(content);
assertThat(actual).isEqualTo(new Foo("Ford", 13));
assertThat(actual.getName()).isEqualTo("Ford");
assertThat(actual.getAge()).isEqualTo(13);
}
}
例子3: 使用@ContextConfiguration
事實上@JsonTest也可以配合@ContextConfiguration一起使用。
源代碼見ThinJsonTest:
@JsonTest
@ContextConfiguration(classes = JsonTest.class)
public class ThinJsonTest extends AbstractTestNGSpringContextTests {
@Autowired
private JacksonTester json;
@Test
public void testSerialize() throws Exception {
// ...
}
@Test
public void testDeserialize() throws Exception {
// ...
}
}
@OverrideAutoConfiguration
在Spring、Spring Boot 和 TestNG 測試指南 ( 1 )提到:
除了單元測試(不需要初始化ApplicationContext的測試)外,盡量將測試配置和生產配置保持一致。比如如果生產配置里啟用了AutoConfiguration,那么測試配置也應該啟用。因為只有這樣才能夠在測試環境下發現生產環境的問題,也避免出現一些因為配置不同導致的奇怪問題。
那么當我們想在測試代碼里關閉Auto Configuration如何處理?
方法1:提供另一套測試配置
方法2:使用@OverrideAutoConfiguration
方法1雖然能夠很好的解決問題,但是比較麻煩。而方法2則能夠不改變原有配置、不提供新的配置的情況下,就能夠關閉Auto Configuration。
在本章節的例子里,我們自己做了一個Auto Configuration類,AutoConfigurationEnableLogger:
@Configuration
public class AutoConfigurationEnableLogger {
private static final Logger LOGGER = LoggerFactory.getLogger(AutoConfigurationEnableLogger.class);
public AutoConfigurationEnableLogger() {
LOGGER.info("Auto Configuration Enabled");
}
}
并且在META-INF/spring.factories里注冊了它:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=
me.chanjar.annotation.overrideac.AutoConfigurationEnableLogger
這樣一來,只要Spring Boot啟動了Auto Configuration就會打印出日志:
2017-08-24 16:44:52.789 INFO 13212 --- [ main] m.c.a.o.AutoConfigurationEnableLogger : Auto Configuration Enabled
例子1:未關閉Auto Configuration
源代碼見BootTest:
@SpringBootTest
@SpringBootApplication
public class BootTest extends AbstractTestNGSpringContextTests {
@Test
public void testName() throws Exception {
}
}
查看輸出的日志,會發現Auto Configuration已經啟用。
例子2:關閉Auto Configuration
然后我們用@OverrideAutoConfiguration關閉了Auto Configuration。
源代碼見BootTest:
@SpringBootTest
@OverrideAutoConfiguration(enabled = false)
@SpringBootApplication
public class BootTest extends AbstractTestNGSpringContextTests {
@Test
public void testName() throws Exception {
}
}
再查看輸出的日志,就會發現Auto Configuration已經關閉。
@TestConfiguration
@TestConfiguration是Spring Boot Test提供的一種工具,用它我們可以在一般的@Configuration之外補充測試專門用的Bean或者自定義的配置。
@TestConfiguration實際上是一種@TestComponent,@TestComponent是另一種@Component,在語義上用來指定某個Bean是專門用于測試的。
需要特別注意,你應該使用一切辦法避免在生產代碼中自動掃描到@TestComponent。 如果你使用@SpringBootApplication啟動測試或者生產代碼,@TestComponent會自動被排除掉,如果不是則需要像@SpringBootApplication一樣添加TypeExcludeFilter:
//...
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
// ...})
public @interface SpringBootApplication
例子1:作為內部類
@TestConfiguration和@Configuration不同,它不會阻止@SpringBootTest去查找機制(在Chapter 1: 基本用法 – 使用Spring Boot Testing工具 – 例子4提到過),正如@TestConfiguration的javadoc所說,它只是對既有配置的一個補充。
所以我們在測試代碼上添加@SpringBootConfiguration,用@SpringBootTest(classes=…)或者在同package里添加@SpringBootConfiguration類都是可以的。
而且@TestConfiguration作為內部類的時候它是會被@SpringBootTest掃描掉的,這點和@Configuration一樣。
測試代碼TestConfigurationTest:
@SpringBootTest
@SpringBootConfiguration
public class TestConfigurationTest extends AbstractTestNGSpringContextTests {
@Autowired
private Foo foo;
@Test
assertEquals(foo.getName(), "from test config");
}
@TestConfiguration
public class TestConfig {
@Bean
public Foo foo() {
return new Foo("from test config");
}
}
}
例子2:對@Configuration的補充和覆蓋
@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");
}
}
測試代碼TestConfigurationTest:
@SpringBootTest(classes = { Config.class, TestConfig.class })
public class TestConfigurationTest extends AbstractTestNGSpringContextTests {
@Qualifier("foo")
@Autowired
private Foo foo;
@Qualifier("foo2")
@Autowired
private Foo foo2;
@Test
assertEquals(foo.getName(), "from test config");
assertEquals(foo2.getName(), "from test config2");
}
}
再查看輸出的日志,就會發現Auto Configuration已經關閉。
例子3:避免@TestConfiguration被掃描到
在上面的這個例子里的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
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
assertNull(testConfig);
}
}
參考文檔
Spring框架測試
http://docs.spring.io/spring/docs/4.3.9.RELEASE/spring-framework-reference/htmlsingle/#testing
春季啟動測試
http://docs.spring.io/spring-boot/docs/1.5.4.RELEASE/reference/htmlsingle/#boot-features-testing
具有測試屬性源的上下文配置
https://docs.spring.io/spring/docs/4.3.9.RELEASE/spring-framework-reference/html/integration-testing.html#testcontext-ctx-management-property-sources
Spring Framework Testing
http://docs.spring.io/spring/docs/4.3.9.RELEASE/spring-framework-reference/htmlsingle/#testing
Spring Boot Testing
http://docs.spring.io/spring-boot/docs/1.5.4.RELEASE/reference/htmlsingle/#boot-features-testing
@JsonTest
http://docs.spring.io/spring-boot/docs/1.5.4.RELEASE/reference/htmlsingle/#boot-features-testing-spring-boot-applications-testing-autoconfigured-json-tests
JsonComponent
http://docs.spring.io/spring-boot/docs/1.5.4.RELEASE/api/org/springframework/boot/jackson/JsonComponent.html
JacksonAutoConfiguration
http://docs.spring.io/spring-boot/docs/1.5.4.RELEASE/api/org/springframework/boot/autoconfigure/jackson/JacksonAutoConfiguration.html
JacksonTester
http://docs.spring.io/spring-boot/docs/1.5.4.RELEASE/api/org/springframework/boot/test/json/JacksonTester.html
GsonTester
http://docs.spring.io/spring-boot/docs/1.5.4.RELEASE/api/org/springframework/boot/test/json/GsonTester.html
BasicJsonTester
http://docs.spring.io/spring-boot/docs/1.5.4.RELEASE/api/org/springframework/boot/test/json/BasicJsonTester.html
Detecting test configuration
https://docs.spring.io/spring-boot/docs/1.5.4.RELEASE/reference/htmlsingle/#boot-features-testing-spring-boot-applications-detecting-config
Excluding test configuration
https://docs.spring.io/spring-boot/docs/1.5.4.RELEASE/reference/htmlsingle/#boot-features-testing-spring-boot-applications-excluding-config
責任編輯:
總結
以上是生活随笔為你收集整理的boot spring test 文档_Spring、Spring Boot 和 TestNG 测试指南 ( 3 )的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 在游戏中找到真人客服,需要多久?
- 下一篇: 华为3年完成13000器件替代开发!任正