差異處

這裏顯示兩個版本的差異處。

連向這個比對檢視

java:spring:test:springinjunithellowworld [2019/01/30 23:49]
tony
java:spring:test:springinjunithellowworld [2023/06/25 09:48]
行 1: 行 1:
-{{tag>​java junit spring spring-test}} +
-====== Spring In JUnit HelloWorld! ====== +
-===== Introduction ===== +
-在寫這篇文章前,我只使用Spring Test去測試過我們的REST API。某一日,因為看到同事誤用的@ActiveProfile,讓我發現了其它不錯的Test Annotation。本篇文章分享給大家一些基本寫法。 +
-\\ +
-Note. 我使用的spring-test版本是4.3.6。 +
-===== Load & Close Spring Context ===== +
-下面這段是在修改之前的Load與Close Spring Context的程式碼,會註冊兩個Config,並將我們需要的物件綁定到此TestCase物件上:​ +
-<code java> +
-private AnnotationConfigApplicationContext springContext;​ +
-@Before +
-public void setup(){ +
- springContext = new AnnotationConfigApplicationContext();​ +
- springContext.setEnvironment(env);​ +
- springContext.register( +
- ModelConfig.class,​ +
- MockConfig.class +
- ); +
-  +
- springContext.refresh();​ +
-  +
- springContext.getAutowireCapableBeanFactory().autowireBean(this);​ +
-+
-  +
-@After +
-public void teardown(){ +
- springContext.close();​ +
-+
-</​code>​ +
-上面冗長的程式碼,只要使用以下Annotation,就可以達到Load與Close:​ +
-<code java> +
-@RunWith(SpringRunner.class) +
-@ContextConfiguration(classes={ModelConfig.class,​ MyTest.MockConfig.class}) +
-public class RedfishSpringConfigTest { +
- // skip +
-+
-</​code>​ +
-Runner要使用SpringRunner,而ContextConfiguration可以指定你要載入的Config class;假如你的config是xml形式,可以使用下面的寫法讓它去你的classpath找設定檔:​ +
-<code java> +
-@ContextConfiguration("​myconfig.xml"​) +
-</​code>​ +
-===== Get Bean ===== +
-在執行測試過程中,一定會需要從Spring Context中取得你需要的Bean進行測試,以下是舊的寫法:​ +
-<code java> +
-AppController controller = springContext.getBean(AppController.class);​ +
-</​code>​ +
-在透過SpringRunner執行測試案例後,你可以直接在測試案例中綁定資源,以下是@Autowired寫法:​ +
-<code java> +
-@Autowired +
-private AppController appController;​ +
-</​code>​ +
-===== Environment ===== +
-在你的Spring Config中,你可能會讀取properties並透過Environment去取得你要的參數;而測試中也免不了需要賦予這些參數來確認功能是否正常,以下是舊的寫法:​ +
-<code java> +
-MockEnvironment env = new MockEnvironment();​ +
-env.setProperty("​interval",​ String.valueOf(expectedInterval));​ +
-env.setProperty("​timeout",​ String.valueOf(expectedTimeout));​ +
-  +
-springContext = new AnnotationConfigApplicationContext();​ +
-springContext.setEnvironment(env);​ +
-</​code>​ +
-假如要將測試的MockEnvironment帶入Spring Context中,這時候就要依靠ApplicationContextInitializer:​ +
-<code java> +
-public static class EnvInitializer implements ApplicationContextInitializer<​ConfigurableApplicationContext>​ { +
- @Override +
- public void initialize(ConfigurableApplicationContext applicationContext) { +
- MockEnvironment env = new MockEnvironment();​ +
- env.setProperty("​interval",​ String.valueOf(expectedInterval));​ +
- env.setProperty("​timeout",​ String.valueOf(expectedTimeout));​ +
- applicationContext.setEnvironment(env);​ +
-+
-+
-</​code>​ +
-最後就是透過@ContextConfiguration載入這個EvnInitializer:​ +
-<code java> +
-@ContextConfiguration(classes={ModelConfig.class,​ MyTest.MockConfig.class},​initializers=MyTest.EvnInitializer.class) +
-</​code>​ +
-嗯..似乎要寫更多的code。其實還有另外一個方案,就是使用@TestPropertySource去指定參數:​ +
-<​code>​ +
-@TestPropertySource(properties={"​interval=123","​timeout=456"​}) +
-</​code>​ +
-但使用@TestPropertySource,如果要串變數上去,反而可讀性就不是這麼好了。 +
-===== LifeCycle of the Spring Context ===== +
-在舊的寫法中,Spring Context的生命週期取決於我將Load與Close放在哪裡;而spring-text則是提供了@DirtiesContext讓你設定設定生命週期。用法如下,我指定在整個test suite執行後才清除context:​ +
-<code java> +
-@DirtiesContext(classMode=ClassMode.AFTER_CLASS) +
-</​code>​ +
-除了上面這個,常會使用的還有ClassMode.AFTER_EACH_TEST_METHOD。至於要用哪一種,可以好好思考,畢竟Spring的Load與Close是相當花時間的。 +
-===== Reference ===== +
-  * [[https://​docs.spring.io/​spring/​docs/​current/​spring-framework-reference/​testing.html#​testing|Official Document]] +
-  * [[http://​blog.jamesdbloom.com/​UsingPropertySourceAndEnvironment.html|UsingPropertySourceAndEnvironment]] +
-  * [[https://​www.solidsyntax.be/​2013/​10/​22/​clean-the-spring-context-between-tests/​|Clean Spring Context]] +
-=====    ===== +
----- +
-\\ +
-~~DISQUS~~+