最近第一次嘗試寫基於 Spring Boot 的應用程式,使用了 CommandLineRunner 來作為應用程式的入口。寫的過程因為想要方便後面做單元測試,因此盡可能地把商業邏輯都寫在 CommandLineRunner 裡頭。不過結果最後在跑單元測試時,卻發現 SpringBootTest 啟動的程序會先執行 CommandLineRunner….囧rz。
簡單搜尋一下之後,感覺上好像是因為 Spring Boot 有個啟動設定的程序,然後一般來說會因為自動搜尋設定的關係,導致它自動搜尋到 CommandLineRunner,然後就開始執行它了 。所以該做的事情是,要在單元測試中給他一個獨特的啟動設定,並且在這個啟動設定中要求忽略 CommandLineRunner。
PS. 不過這解釋也只是感覺而已,其實因為我也還沒認真閱讀過 Spring Boot 文件,很有可能其實我猜想的解釋是錯的 XD。但動作上是可以這麼做來避免單元測試時執行 CommandLineRunner 沒錯。
具體來說,可以先在 src/test/java 中加入一個給單元測試使用的啟動設定,其中要在 ComponentScan 中指定要忽略 CommandLineRunner。
import org.springframework.boot.CommandLineRunner; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.FilterType; @Configuration @ComponentScan(excludeFilters = @ComponentScan.Filter( type = FilterType.ASSIGNABLE_TYPE, value = CommandLineRunner.class)) @EnableAutoConfiguration public class TestApplication { }
接著在單元測試的類別上,指定 SpringBootTest 要從剛剛建立的類別去啟動。
@SpringBootTest(classes = TestApplication.class) @ExtendWith(SpringExtension.class) public class MyUnitTest { .... }
另外提一下,這裡用的是 JUnit 5,所以 annotation 寫法跟 JUnit 4 有些不同。
沒有留言:
張貼留言