Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
今こそ知りたいSpring Test / Spring Fest 2020
Search
Ryo Shindo
December 17, 2020
Programming
11
5.8k
今こそ知りたいSpring Test / Spring Fest 2020
Spring Fest 2020 Beginner Track
https://springfest2020.springframework.jp/
Ryo Shindo
December 17, 2020
Tweet
Share
More Decks by Ryo Shindo
See All by Ryo Shindo
こわくないソースコードリーディング生活 / JJUG CCC 2019 Fall
rshindo
15
9.2k
開発者のためのSpring Boot Actuator入門 / jsug-2019-08
rshindo
5
5.7k
早わかりSpring Data JDBC / jsug-2019-01
rshindo
5
4.1k
ふつうのJavaアプリ開発のための自動テスト戦略 / JJUG CCC 2018 Fall
rshindo
9
4.9k
Spring WebFluxで学ぶReactive Application / Introduction to Reactive
rshindo
1
2.2k
まだまだ間に合う!JUnit 5入門 / JJUG CCC 2018 Spring
rshindo
6
3.2k
Spring Data JDBCを使い倒す! / Intruduction to Spring Data JDBC
rshindo
4
2.2k
Other Decks in Programming
See All in Programming
「Chatwork」Android版アプリを 支える単体テストの現在
okuzawats
0
180
採用事例の少ないSvelteを選んだ理由と それを正解にするためにやっていること
oekazuma
2
1k
MCP with Cloudflare Workers
yusukebe
2
220
range over funcの使い道と非同期N+1リゾルバーの夢 / about a range over func
mackee
0
110
開発者とQAの越境で自動テストが増える開発プロセスを実現する
92thunder
1
180
今年一番支援させていただいたのは認証系サービスでした
satoshi256kbyte
1
250
Security_for_introducing_eBPF
kentatada
0
110
PHPで作るWebSocketサーバー ~リアクティブなアプリケーションを知るために~ / WebSocket Server in PHP - To know reactive applications
seike460
PRO
2
320
SymfonyCon Vienna 2025: Twig, still relevant in 2025?
fabpot
3
1.2k
フロントエンドのディレクトリ構成どうしてる? Feature-Sliced Design 導入体験談
osakatechlab
8
4.1k
return文におけるstd::moveについて
onihusube
1
1.1k
ドメインイベント増えすぎ問題
h0r15h0
2
300
Featured
See All Featured
Designing on Purpose - Digital PM Summit 2013
jponch
116
7k
BBQ
matthewcrist
85
9.4k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
507
140k
Visualization
eitanlees
146
15k
The MySQL Ecosystem @ GitHub 2015
samlambert
250
12k
Principles of Awesome APIs and How to Build Them.
keavy
126
17k
The Invisible Side of Design
smashingmag
298
50k
Imperfection Machines: The Place of Print at Facebook
scottboms
266
13k
No one is an island. Learnings from fostering a developers community.
thoeni
19
3k
Thoughts on Productivity
jonyablonski
67
4.4k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
656
59k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
26
1.5k
Transcript
1 Copyright © Acroquest Technology Co., Ltd. All rights reserved.
今こそ知りたいSpring Test Spring Fest 2020 Acroquest Technology株式会社 進藤 遼(@shindo_ryo)
自己紹介 • 進藤 遼 • Acroquest Technology株式会社 • 日本Springユーザ会 スタッフ
• Twitter: @shindo_ryo • 好きなSpring Projectは Spring Cloud Sleuth Copyright © Acroquest Technology Co., Ltd. All rights reserved. 2
目次 Copyright © Acroquest Technology Co., Ltd. All rights reserved.
3 1. Spring Testの基礎 2. モックテスト 3. DBテスト 4. Spring Webテスト 5. Spring Bootテスト 6. その他
Spring Testの基礎 Copyright © Acroquest Technology Co., Ltd. All rights
reserved. 4
Spring Testとは Copyright © Acroquest Technology Co., Ltd. All rights
reserved. 5 1. Springアプリケーションに対するインテグレーションテストを サポートするモジュール 2. JUnit, TestNGといったテスティングフレームワークと連携する ※デフォルトでJUnit 5 3. Spring MVCのテスト、DBテストなどを容易にする ユーティリティを多数提供
Spring Testのインストール Copyright © Acroquest Technology Co., Ltd. All rights
reserved. 6 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> デフォルトで設定済み
SpringのDIの仕組み Copyright © Acroquest Technology Co., Ltd. All rights reserved.
7 DIコンテナ (ApplicationContext) Bean Bean 使う new new 依存オブジェクトを注入
SpringのDIの仕組み Copyright © Acroquest Technology Co., Ltd. All rights reserved.
8 @Service public class FooService { private final BarService barService; public FooService(BarService barService) { this.barService = barService; } public String foobar() { return "foo" + barService.bar(); } } @Service public class BarService { private final MessageSource messageSource; public BarService(MessageSource messageSource) { this.messageSource = messageSource; } public String name() { return messageSource.getMessage( "name", null, Locale.getDefault()); } } DIコンテナが依存オブジェクトを注入
通常のユニットテスト Copyright © Acroquest Technology Co., Ltd. All rights reserved.
9 public class FooServiceTest { FooService service; @BeforeEach void beforeEach() { service = //何らかの方法で初期化 } @Test void testHello() { assertEquals("Hi, Spring Fest 2020", service.hello()); } }
Spring Testを使わないと・・・ Copyright © Acroquest Technology Co., Ltd. All rights
reserved. 10 1. 全てのインスタンスを自前でnew ➢ controller層からrepository層まで統合しようとすると 非常に多くのBeanが必要になる 2. 正しくDIできることをテストできない ➢ Beanが不足、または重複していても気づけない
Spring Testを使うと・・・ Copyright © Acroquest Technology Co., Ltd. All rights
reserved. 11 @ExtendWith(SpringExtension.class) ・・・① @ContextConfiguration( ・・・② locations = “classpath:/application-context.xml”) public class FooServiceTest { @Autowired ・・・③ FooService service; @Test void testHello() { assertEquals("Hi, Spring Fest 2020", service.hello()); } } ①JUnitとSpring Testを 連携させる ②ApplicationContextの 設定ファイルを指定 (classesでJava Configも 指定可能) ③テスト対象Beanを取得
Spring Bootの場合 Copyright © Acroquest Technology Co., Ltd. All rights
reserved. 12 @SpringBootTest public class FooServiceTest { @Autowired FooService service; @Test void testHello() { assertEquals("Hi, Spring Fest 2020", service.hello()); } } @SpringBootApplicationがついたクラスを探索し、 設定を自動的に読み込む。 ※@ExtendWith(SpringExtension.class)は @SpringBootTestの中で指定されている。 (Boot 2.1~)
Spring TestContextフレームワーク Copyright © Acroquest Technology Co., Ltd. All rights
reserved. 13 SpringExtension TestContextManager TestContext テストクラスと ApplicationContextを セットにして管理 ApplicationContext テストクラス @Autowired FooService service; TestExecutionListener use create Spring Bean テストコードの設定に対応 するApplicationContextを ロード 依存オブジェクトの注入と いった、テストの前処理・ 後処理を実行 ApplicationContextは キャッシュされて使い回される
テスト実行フロー Copyright © Acroquest Technology Co., Ltd. All rights reserved.
14 テストクラスのロード ApplicationContextの初期化 テストクラスにSpring Beanを注入 各テストメソッドを実行 SpringExtension @Test JUnit
スライステスト Copyright © Acroquest Technology Co., Ltd. All rights reserved.
15 • 全てのBeanを初期化するには時間がかかる • テスト対象に必要なBeanのみを初期化したい →スライステスト @WebMvcTest @WebFluxTest @JsonTest @RestClientTest @WebServiceClientTest @DataJpaTest @DataCassandraTest @JdbcTest @DataJdbcTest @DataLdapTest @DataMongoTest @DataNeo4jTest @DataR2dbcTest @DataRedisTest @JooqTest Boot
モックテスト Copyright © Acroquest Technology Co., Ltd. All rights reserved.
16
Mockito連携 Copyright © Acroquest Technology Co., Ltd. All rights reserved.
17 1. spring-boot-starter-testでは、デフォルトでMockitoを使った Beanのモック化機能が提供 2. @MockBean / @SpyBean でBeanをモック化し、 振る舞いを変えることができる FooService BarService BarService @MockBean
@MockBean / @SpyBean Copyright © Acroquest Technology Co., Ltd. All
rights reserved. 18 @SpringBootTest public class FooServiceTest { @Autowired FooService service; @MockBean BarService barService; @Test void testHello() { Mockito.when(barService.name()).thenReturn("Mocked Response"); assertEquals("Hi, Mocked Response", service.hello()); } } フィールドにアノテーションを つけることで、Beanが自動的に モック化される(@SpyBeanも同様) Mock化された振る舞いを指定
@MockBean / @SpyBean Copyright © Acroquest Technology Co., Ltd. All
rights reserved. 19 @SpringBootTest @MockBean(BarService.class) public class FooServiceTest { @Autowired FooService service; @Autowired BarService barService; @Test void testHello() { Mockito.when(barService.name()).thenReturn("Mocked Response"); assertEquals("Hi, Mocked Response", service.hello()); } } クラスアノテーションでも指定可能 その場合は@Autowiredで注入する
Q. ApplicationContextの起動回数は? Copyright © Acroquest Technology Co., Ltd. All rights
reserved. 20 @SpringBootTest public class BarServiceTest { @Autowired BarService service; @MockBean MessageSource messageSource; @Test void testBar() { // 省略 } } @SpringBootTest public class FooServiceTest { @Autowired FooService service; @MockBean BarService barService; @Test void testHello() { // 省略 } } モック化する Beanが異なる
@MockBeanと実行時間 Copyright © Acroquest Technology Co., Ltd. All rights reserved.
21 A. 2回 ⇒起動回数が増え、実行時間が遅くなりがち ApplicationContext ApplicationContext FooService BarService MessageSource FooService MessageSource BarService TestContext(FooServiceTest) TestContext(BarServiceTest) ApplicationContextが異なるため、 キャッシュが使われない モック化されたBeanは モックでないBeanとは 別のもの扱いとなる
モックテストでも遅くならないようにする方法 Copyright © Acroquest Technology Co., Ltd. All rights reserved.
22 1. 各テストクラスでモック対象のクラスを完全に同一にする • 共通のJava Configを作って@ContextConfigurationで指定 • 一つでも違う部分があるとアウト 2. @MockBean/@SpyBeanを使わない • モックを使うテストではSpring Testを使わない • モッククラスを自作して、テスト中は@Primaryで差し替え @Service @Primary public class MockBarService { }
DBテスト Copyright © Acroquest Technology Co., Ltd. All rights reserved.
23
DBテストのフロー Copyright © Acroquest Technology Co., Ltd. All rights reserved.
24 テストデータのセットアップ テストの実行 更新後のデータの検証 ロールバック / テストデータの破棄 テストデータの状態を一定に保つことで テストのべき等性を担保する
テストデータのセットアップの2つの方法 Copyright © Acroquest Technology Co., Ltd. All rights reserved.
25 ① schema.sql / data.sql をクラスパスに配置する • DataSourceの初期化の段階で自動的に実行される • テストクラスごと、テストメソッドごとのような実行サイクルはできない ② テストクラス、テストメソッドに@Sqlを指定する • 任意のSQLファイルを読み込み実行する • テストメソッドの前後で実行させることができる
@Sql Copyright © Acroquest Technology Co., Ltd. All rights reserved.
26 @DataJpaTest @Sql(scripts = "classpath:/employee.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) public class EmployeeRepositoryTest { @Autowired EmployeeRepository repository; @Test void testFind() { Employee employee = repository.findById(1L).get(); assertEquals("shindo", employee.getName()); } } TRUNCATE TABLE employee; INSERT INTO employee(employee_id, name) VALUES ('1', 'shindo'); AFTER_TEST_METHOD も指定可能
トランザクション管理 Copyright © Acroquest Technology Co., Ltd. All rights reserved.
27 • ロールバックしないと・・・ DB テスト1回目 INSERT INTO employee (employee_id, name) VALUES(1, ‘shindo’); テスト2回目 INSERT INTO employee (employee_id, name) VALUES(1, ‘shindo’); employee (id=1, name=shindo) PK重複 employee (id=1, name=shindo)
@Transactionalでロールバック Copyright © Acroquest Technology Co., Ltd. All rights reserved.
28 @DataJpaTest public class EmployeeRepositoryTest { @Autowired EmployeeRepository repository; @Autowired JdbcTemplate jdbcTemplate; @Autowired EntityManager entityManager; @Test @Transactional void testSave() { Employee employee = new Employee(); employee.setName("spring"); employee = repository.save(employee); entityManager.flush(); int count = JdbcTestUtils.countRowsInTable(jdbcTemplate, "employee"); assertEquals(1, count); } } テストメソッドがトランザクション境界となり、 メソッドが終わると自動でロールバックされる コミットさせたい場合は、@Transactionalの代わりに @Commitを使う
JPA Repositoryの場合はflush()が必要 Copyright © Acroquest Technology Co., Ltd. All rights
reserved. 29 @DataJpaTest public class EmployeeRepositoryTest { @Autowired EmployeeRepository repository; @Autowired JdbcTemplate jdbcTemplate; @Autowired EntityManager entityManager; @Test @Transactional void testSave() { Employee employee = new Employee(); employee.setName("spring"); employee = repository.save(employee); entityManager.flush(); int count = JdbcTestUtils.countRowsInTable(jdbcTemplate, "employee"); assertEquals(1, count); } } トランザクション境界の前にflush()して SQLを発行させる JPAについて詳しくは@suke_masaの 資料を参照
実行結果の検証 Copyright © Acroquest Technology Co., Ltd. All rights reserved.
30 1. JdbcTemplateでテーブルをクエリする 2. JdbcTestUtils • テーブル名を指定するだけで行数などを取得できる • 行、テーブルの削除も可能 @Test @Transactional void testSave() { Employee employee = new Employee(); employee.setName("spring"); employee = repository.save(employee); entityManager.flush(); // JdbcTemplateを使う場合 int count = jdbcTemplate.queryForObject("select count(*) from employee", Integer.class); assertEquals(1, count); // JdbcTestUtilsを使う場合 count = JdbcTestUtils.countRowsInTable(jdbcTemplate, "employee"); assertEquals(1, count); }
DBテストフレームワーク Copyright © Acroquest Technology Co., Ltd. All rights reserved.
31 1. DBUnit ➢ xml, excelなどでテストデータのセットアップと結果の検証ができる ➢ 設定用のコードが多く必要だったり、JUnit 5に追従できていなかったりと不 便。 2. Database Rider ➢ DBUnitをベースに、アノテーションで楽に設定できるように ➢ Springとの連携も容易
Spring Webテスト Copyright © Acroquest Technology Co., Ltd. All rights
reserved. 32
MockMvcとは Copyright © Acroquest Technology Co., Ltd. All rights reserved.
33 1. サーバーにデプロイせずに、Spring MVCのインテグレーションテ ストを支援するためのクラス 2. DispatcherServletに擬似的なリクエストを投げて、パスに対応す るHandlerを呼び出す
MockMvcの仕組み Copyright © Acroquest Technology Co., Ltd. All rights reserved.
34 ① リクエストパスやパラメータなどを設定 ② 疑似的なリクエストを行う ③ リクエスト内容に一致するHandlerを呼び出す ④ レスポンス内容の検証を行う テストコード MockMvc DispatcherServlet Handler (Controller) Spring MVC ① ② ③ ④
GETメソッドのテスト Copyright © Acroquest Technology Co., Ltd. All rights reserved.
35 @SpringBootTest @AutoConfigureMockMvc public class HelloControllerTest { @Autowired MockMvc mockMvc; @Test void testHello() throws Exception { mockMvc.perform( MockMvcRequestBuilders.get("/hello").accept(MediaType.TEXT_PLAIN) ) .andExpect( MockMvcResultMatchers.status().is2xxSuccessful()) .andExpect( MockMvcResultMatchers.content().string("Hi, Spring Fest 2020")); } } Spring Bootの場合は このアノテーションだけで設定可能 リクエスト内容、検証内容を メソッドチェーンで記述する
GETメソッドのテスト Copyright © Acroquest Technology Co., Ltd. All rights reserved.
36 @SpringBootTest @AutoConfigureMockMvc public class HelloControllerTest { @Autowired MockMvc mockMvc; @Test void testHello() throws Exception { mockMvc.perform( get("/hello").accept(MediaType.TEXT_PLAIN) ) .andExpect(status().is2xxSuccessful()) .andExpect(content().string("Hi, Spring Fest 2020")); } }
POSTメソッドのテスト Copyright © Acroquest Technology Co., Ltd. All rights reserved.
37 @Autowired ObjectMapper objectMapper; @Test void testCalc() throws Exception { CalcRequest request = new CalcRequest(); request.setLeftSide(2); request.setRightSide(3); request.setOperator("+"); mockMvc.perform( post("/calc") .content(objectMapper.writeValueAsBytes(request)) .contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON) ) .andExpect(status().is2xxSuccessful()) .andExpect(jsonPath("$.result", CoreMatchers.is(5.0))); } JSONのリクエストは要シリアライズ JSONのフィールドを検証可能
デバッグロギング Copyright © Acroquest Technology Co., Ltd. All rights reserved.
38 @Test void testHello() throws Exception { mockMvc.perform( get("/hello").accept(MediaType.TEXT_PLAIN) ) .andDo(MockMvcResultHandlers.print()) (後略) (一部) MockHttpServletResponse: Status = 200 Error message = null Headers = [Content-Type:"text/plain;charset=UTF-8", Content-Length:"20"] Content type = text/plain;charset=UTF-8 Body = Hi, Spring Fest 2020 Forwarded URL = null Redirected URL = null Cookies = [] print()の場合は標準出力 log()も利用可
Web API アクセスのモック化 Copyright © Acroquest Technology Co., Ltd. All
rights reserved. 39 Web API Springアプリケーション HTTP モック テストのときはHTTPコールを モック化したい
MockRequestServiceServer Copyright © Acroquest Technology Co., Ltd. All rights reserved.
40 1. RestTemplateのふるまいをモック化するクラス 2. RestTemplateの内部のClientHttpRequestFactoryをモックに差 し替えることで、RestTemplateを使っているコードを変更するこ となく、HTTPコールをモック化できる RestTemplate <interface> ClientHttpRequest Factory HttpComponentsClient HttpRequestFactory MockClientHttp RequestFactory
MockRequestServiceServer Copyright © Acroquest Technology Co., Ltd. All rights reserved.
41 @SpringBootTest class WeatherForecastApiRepositoryTest { @Autowired WeatherForecastApiRepository repository; @Autowired RestTemplate restTemplate; @Test void retrieveForecastAt() { MockRestServiceServer server = MockRestServiceServer.bindTo(restTemplate).build(); server.expect(MockRestRequestMatchers.method(HttpMethod.GET)) .andExpect(requestTo("http://foo.domain/forecast?location=Tokyo")) .andRespond(MockRestResponseCreators.withSuccess() .contentType(MediaType.APPLICATION_JSON) .body("{¥"location¥":¥"Tokyo¥",¥"weather¥":¥"sunny¥"}")); Forecast actual = repository.retrieveForecastAt("Tokyo"); assertEquals("Tokyo", actual.getLocation()); assertEquals("sunny", actual.getWeather()); } } RestTemplateはテスト対象のBeanを取得 RestTemplateの中身をモックに差し替え モックのふるまいを設定する
Spring Bootテスト Copyright © Acroquest Technology Co., Ltd. All rights
reserved. 42
@SpringBootTest Copyright © Acroquest Technology Co., Ltd. All rights reserved.
43 1. Spring Bootアプリケーションをテストするためのアノテーション 2. @SpringBootApplicationを検知して各種設定を自動的にロード 3. 組み込みサーブレットコンテナを実際に立ち上げて、 本物のHTTPリクエスト/レスポンスを投げてテストができる
Copyright © Acroquest Technology Co., Ltd. All rights reserved. 44
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) public class ApiTest { @LocalServerPort int port; @Test void testHello() { RestTemplate restTemplate = new RestTemplate(); String url = "http://localhost:" + port + "/hello"; ResponseEntity<String> entity = restTemplate.getForEntity(url, String.class); assertEquals(HttpStatus.OK, entity.getStatusCode()); assertEquals("Hi, Spring Fest 2020", entity.getBody()); } } ランダムなポートでサーバーを起動 サーバーポートを取得 RestTemplateを使って 本物のHTTPリクエストを実行
WebEnvironment Copyright © Acroquest Technology Co., Ltd. All rights reserved.
45 • @SpringBootTestで指定できるWebEnvironmentは下記の通り No WebEnvironment 1 MOCK (デフォルト) モックサーブレット環境を構成する。(実際のポートはリッスンしな い) @AutoConfigureMockMvcを組み合わせる。 2 RANDOM_PORT 組み込みサーブレットコンテナを起動し、ランダムなポートをリッス ンする。 3 DEFINED_PORT 組み込みサーブレットコンテナを起動し、プロパティで定義されたポ ートをリッスンする。 4 NONE ApplicationContextをロードするが、サーブレット環境を構成しな い。 バッチなどの非Webアプリケーションで利用する。
MockMvcとの違い Copyright © Acroquest Technology Co., Ltd. All rights reserved.
46 RANDOM_PORT/ DEFINED_PORT MockMvc 実行環境 組み込みサーブレットコンテナ を実際に起動 モックサーブレット 起動時間 実環境と同一なため 低速 モック環境のため (比較的)高速 トランザクション ロールバック不可 @Transactionalで ロールバック可能 テストメソッドとは別のスレッドで処理が 実行されるため、テストコードから トランザクション管理できない
TestRestTemplate Copyright © Acroquest Technology Co., Ltd. All rights reserved.
47 1. インテグレーションテスト用のRestTemplate 2. webEnvironment=RANDOM_PORT/DEFINED_PORT の場合に、サーバーポートが自動的に設定される 3. デフォルトでクッキーとリダイレクトが無効化されている
TestRestTemplate Copyright © Acroquest Technology Co., Ltd. All rights reserved.
48 @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) public class ApiTest { @Autowired TestRestTemplate restTemplate; @Test void testHello() { ResponseEntity<String> entity = restTemplate.getForEntity("/hello", String.class); assertEquals(HttpStatus.OK, entity.getStatusCode()); assertEquals("Hi, Spring Fest 2020", entity.getBody()); } } @LocalServerPort不要
WebTestClient Copyright © Acroquest Technology Co., Ltd. All rights reserved.
49 1. インテグレーションテスト用のWebClient 2. TestRestTemplateと同様、サーバーポートが自動的に 設定される 3. レスポンスの検証を流れるようなインターフェースで記述できる 4. 要spring-boot-starter-webflux
WebTestClient Copyright © Acroquest Technology Co., Ltd. All rights reserved.
50 @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) public class ApiTest { @Autowired WebTestClient client; @Test void testHello() { client.get().uri("/hello") .exchange() .expectStatus().isOk() .expectBody(String.class).isEqualTo("Hi, Spring Fest 2020"); } }
その他小ネタ Copyright © Acroquest Technology Co., Ltd. All rights reserved.
51
MockMvcWebTestClient Copyright © Acroquest Technology Co., Ltd. All rights reserved.
52 @ExtendWith(SpringExtension.class) @WebMvcTest(controllers = HelloController.class) public class WebTestClientTest { @Autowired WebApplicationContext wac; WebTestClient client; @BeforeEach void setup() { client = MockMvcWebTestClient.bindToApplicationContext(wac).build(); } @Test void testWebTestClient() { client.get() .uri("/hello") .exchange() .expectStatus().isOk() .expectBody(String.class).isEqualTo("Hi, Spring Fest 2020"); } } 詳しくは@makingの 『What's New in Spring 5.3 and Spring Boot 2.4』 をチェック!
アノテーションが多すぎる問題 Copyright © Acroquest Technology Co., Ltd. All rights reserved.
53 @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @SqlGroup({ @Sql(scripts = "classpath:/employee.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD), @Sql(scripts = "classpath:/truncate.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD) }) public class ApiTest { アノテーション多すぎ 同じレイヤーのテストに対しては、 大体同じアノテーションをつけることになる
合成アノテーションで解決 Copyright © Acroquest Technology Co., Ltd. All rights reserved.
54 @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @SqlGroup({ @Sql(scripts = "classpath:/employee.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD), @Sql(scripts = "classpath:/truncate.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD) }) public @interface ApiTestSupport { } @ApiTestSupport public class ApiTest { 合成アノテーションを作成して共通化する
Furthermore… Copyright © Acroquest Technology Co., Ltd. All rights reserved.
55 • WebFlux Test • spring-security-test • mybatis-spring-boot-starter-test • Testcontainers