Spring Boot 1.3.x の Web アプリを 1.4.x へバージョンアップする ( その15 )( テストクラスのアノテーションを 1.4 のものに変更する )
概要
記事一覧はこちらです。
- 今回の手順で確認できるのは以下の内容です。
- テストクラスのアノテーションを 1.4 のものに変更します。
参照したサイト・書籍
Spring Boot 1.4.0 Release Notes - Test utilities and classes
https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-1.4-Release-Notes#test-utilities-and-classesSpring Boot Reference Guide - 40. Testing
http://docs.spring.io/spring-boot/docs/1.4.5.RELEASE/reference/htmlsingle/#boot-features-testing
目次
- どう書き換えればよいのか?
- 変更する方針を決める
- 全てのテストを
@RunWith(SpringRunner.class)
+@SpringBootTest
に変更してみる - Controller, RestController 以外のテストを
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
に変更してみる - 次回は。。。
手順
どう書き換えればよいのか?
最低限の変更だけ行うのであれば、以下のように書き換えれば動きます。
@RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest(classes = Application.class) @WebAppConfiguration public class LendingapprovalFormValidatorTest {
↓↓↓
@RunWith(SpringRunner.class) @SpringBootTest public class LendingapprovalFormValidatorTest {
@RunWith(SpringJUnit4ClassRunner.class)
→@RunWith(SpringRunner.class)
へ変更します。@SpringBootTest(classes = Application.class)
,@WebAppConfiguration
→@SpringBootTest
へ変更します。
@RunWith(SpringRunner.class)
の方は単純な書き換えなので迷わないのですが、@SpringBootTest
の方は webEnvironment 属性で NONE, MOCK, RANDOM_PORT, DEFINED_PORT のどれを指定すればよいのかが最初よく分かりませんでした。結論としては @SpringBootTest
だけ書けば問題なくテストは動きます(この時はデフォルト値である MOCK が指定された状態です)。
1.3 のアノテーションの時と MOCK, RANDOM_PORT, DEFINED_PORT それぞれを指定した時のテストの実行速度がどれくらい違うのか気になったので src/test/java/ksbysample/webapp/lending/web/lendingapproval/LendingapprovalControllerTest.java で試してみます。NONE はエラーになるので最初から除外します。
テストは LendingapprovalControllerTest.java のクラス名の左側のアイコンをクリックして表示される「Run ‘LendingapprovalControllerTest'」を選択して実行します。
計測時間は IntelliJ IDEA の以下の場所に表示されるものを使用します。
1回目 | 2回目 | 3回目 | 4回目 | 5回目 | 平均 | |
---|---|---|---|---|---|---|
1.3 | 5s 791ms | 6s 128ms | 5s 720ms | 5s 609ms | 6s 56ms | 5s 961ms |
MOCK | 5s 906ms | 6s 43ms | 5s 979ms | 6s 225ms | 5s 910ms | 6s 9ms |
RANDOM_PORT | 5s 657ms | 5s 766ms | 5s 555ms | 5s 207ms | 5s 388ms | 5s 514ms |
DEFINED_PORT | 6s 702ms | 5s 542ms | 5s 694ms | 5s 632ms | 5s 787ms | 5s 871ms |
MOCK で遅いの?と思ったので、この後3回程試してみたところ 5s 625ms、6s 8ms、5s 274ms でした。最後の1回だけはそこそこ速いです。MOCK, RANDOM_PORT, DEFINED_PORT でたいした差はないのではないか?という気がしますが、今ひとつはっきりしませんね。。。
もう1つ思ったのは、Controller のテストでなければ @SpringBootTest
ではなく @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
を指定した方がテストが速いのではないか?という点です。
src/test/java/ksbysample/webapp/lending/web/lendingapproval/LendingapprovalFormValidatorTest.java で試してみます。
1回目 | 2回目 | 3回目 | 4回目 | 5回目 | 平均 | |
---|---|---|---|---|---|---|
1.3 | 215ms | 167ms | 254ms | 207ms | 180ms | 204ms |
NONE | 190ms | 291ms | 180ms | 182ms | 199ms | 208ms |
MOCK | 208ms | 197ms | 201ms | 211ms | 196ms | 202ms |
NONE は2回目が遅かった影響で平均が他と大差なくなっていますが、MOCK と比較すると 10~20ms 程度速くなるような気がします。
変更する方針を決める
まずはシンプルに一律以下のアノテーションに変更してテストが全て成功することを確認してみます。MOCK, RANDOM_PORT, DEFINED_PORT で差がない気がするので、シンプルに @SpringBootTest
だけ書くことにします。
@RunWith(SpringRunner.class) @SpringBootTest public class LendingapprovalFormValidatorTest {
その後で Controller, RestController 以外のテストを @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
に変えて、テストの総実行時間が速くなるのか確認してみたいと思います。
また、Controller, RestController のテストを Controller の機能だけのテストにしていれば @WebMvcTest
アノテーションを使用するのもありだな、と思いましたが、作成してあるテストは Service まで含めたものになっているので、今回 @WebMvcTest
は使いません。Controller は Mock を利用して Controller だけのテストをした方がよいのかもしれません。
全てのテストを @RunWith(SpringRunner.class)
+ @SpringBootTest
に変更してみる
以下の手順でアノテーションを変更します。
- Ctrl+Alt+F で「Find in Path」ダイアログを表示した後、
@RunWith(SpringJUnit4ClassRunner.class)
で project 全体を検索します。 - ヒットした箇所を
@RunWith(SpringRunner.class)
+@SpringBootTest
の組み合わせに変更した後、Ctrl+Alt+o を押して不要な import 文を削除します。
また Spock で書いてあるテストについては以下のように変更します。
@ContextConfiguration(loader = SpringApplicationContextLoader.class, classes = Application.class) @WebAppConfiguration class ValuesHelperTest extends Specification {
↓↓↓
@SpringBootTest class ValuesHelperTest extends Specification {
全てのテストを変更したら clean タスク → Rebuild Project → build タスクを実行してみます。
build タスクは “BUILD SUCCESSFUL” が表示されて成功しました。
Project Tool Window の src/test から「Run ‘All Tests’ with Coverage」を実行してみます。
こちらも全てのテストが成功しました。テストの実行速度も体感的には以前と変わりません、というより少し速くなっているような気がします。
5回計測してみます。
1回目 | 2回目 | 3回目 | 4回目 | 5回目 | 平均 |
---|---|---|---|---|---|
29s 709ms | 29s 431ms | 28s 175ms | 29s 293ms | 29s 344ms | 29s 190ms |
IntelliJ IDEA を 2016.3.4 → 2016.3.5 へ、Git for Windows を 2.11.1 → 2.12.0 へバージョンアップ の記事だと 1m 3s 669ms、Spring Boot 1.3.x の Web アプリを 1.4.x へバージョンアップする ( その13 )( RestTemplate で WebAPI を呼び出している処理に spring-retry でリトライ処理を入れる ) の記事だと 49s 111ms でしたので、やはり速くなっているようです。
Controller, RestController 以外のテストを @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
に変更してみる
以下の手順でアノテーションを変更します。
- Ctrl+Alt+F で「Find in Path」ダイアログを表示した後、
@SpringBootTest
で project 全体を検索します。 - ヒットした箇所のうち、Controller, RestController のテスト以外を
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
に変更します。
全てのテストを変更したら clean タスク → Rebuild Project → build タスクを実行してみます。
build タスクは “BUILD SUCCESSFUL” が表示されて成功しました。
Project Tool Window の src/test から「Run ‘All Tests’ with Coverage」を実行してみると、こちらも全てのテストが成功しました。
5回計測してみます。
1回目 | 2回目 | 3回目 | 4回目 | 5回目 | 平均 |
---|---|---|---|---|---|
29s 314ms | 31s 566ms | 30s 978ms | 30s 473ms | 29s 504ms | 30s 367ms |
少しですが遅くなるようです。MOCK と NONE が混在しているからでしょうか。。。? こちらの変更は元に戻して @SpringBootTest
のみにします。
最初テストクラスのアノテーションはなんか複雑になったような気がしていましたが、@RunWith(SpringRunner.class)
+ @SpringBootTest
を書けば十分でした。実はシンプルになったんですね。
次回は。。。
モックは JMockit で作成していますが、Spring Boot 1.4 から @MockBean アノテーションが提供されて Mockito と組み合わせてモックを作ることが推奨されているようなので、@MockBean + Mockito で作り直してみます。
ソースコード
履歴
2017/03/27
初版発行。