JJUG CCC 2023 Spring で話せなかったロールバック周りについて
先日、JJUG CCC 2023 Spring に登壇してきました!
発表時間的に端折ったロールバック周りについて、この記事で補足しておきます。
Transactional を使用しなかった理由
ユニットテストが遅い問題の一つとして、DirtiesContext を使用してロールバックを行なっていることを挙げました。
テストでロールバックを簡単に行う方法として、Spring の Transactional を使う方法があります。下記のように、テストクラスもしくはテストメソッドに @Transactional
をつけて、テスト中に行われた変更をテスト終了時にロールバックすることができます。
@Service
@RequiredArgsConstructor
public class UserService {
private final UserRepository userRepository;
@Transactional
public void register() {
// ユーザ生成処理
this.userRepository.save(user);
}
}
@SpringBootTest
@Transactional
public class UserServiceTest {
@Autowired
private UserService userService;
@Test
public void register() {
// テストデータの準備
// テスト対象メソッドの実行
this.userService.register();
// 検証
}
}
しかし、今回は Transactional を使用しませんでした。
本番環境とテスト環境で行うことを同じにするためです。
テスト対象のアプリケーションサービスのメソッドには、自身でトランザクション管理を行うものと、そうでないものがあります。Transactional を使用すると、自身でトランザクション管理を行うメソッドをテストする時に問題があります。Transactional のデフォルトの挙動 Propagation.REQUIRED
ではテスト側で開始したトランザクションを使い回すからです。
先ほどの例で言うと、テストデータの準備、テスト対象メソッドの実行、検証が全て同じトランザクション上で実行されることになります。
しかし、本番環境ではこのようなことは起こらないので、本番環境とテスト環境で行うことが異なり、正しくテストが行われることを保証できません。
検証していないのでわからないですが、Transactional のオプションをうまく使って、本番環境と合わせられるかもしれないです。
ただ、仮にそれができたとしても、テストを書くたびに意識するのは難しいですし、うっかり デフォルトの Transactional を使ってしまうかもしれません。
また、ロールバックの問題とは別に、リポジトリを過剰にテストしていて、アプリケーションサービスとリポジトリでテストが重複している問題もあったので、結果的にテストの責務を分離することで高速化を図りました。
ちなみに、単体テストの考え方/使い方 の10章によると、テストデータの後始末は、各テストケースの実行前に行うのがよいみたいです。
JJUG CCC の感想
社内の輪読会で読んだ現場で役立つシステム設計の原則の著者の増田さんのセッション 「これだけは知っておきたいクラス設計の基礎知識」を聞けてよかったです。
「体で覚える」というのが印象的で、インプットするだけでなく、もっと手を動かしていこうと思いました!
私たち BABY JOB は、子育てを取り巻く社会のあり方を変え、「すべての人が子育てを楽しいと思える社会」の実現を目指すスタートアップ企業です。圧倒的なぬくもりと当事者意識をもって、こどもと向き合う時間、そして心のゆとりが生まれるサービスを創出します。baby-job.co.jp/
Discussion
JJUG幹事の多田です。この度はご登壇ありがとうございました!当日その場にはいられなかったのですが、この記事と資料は拝見しました😆
いくつかお聞きしたいことがあるのですが、よろしいでしょうか?
多田さん、コメントありがとうございます!
こちらこそ登壇の機会をいただきありがとうございました。
以下ご質問への回答です。
おっしゃる通り、本番と同じDBをコンテナ等で用意できるとよいのですが、以下を考慮してH2を使用しています。
そんな設定ができたんですね。知りませんでした!
テスト環境と本番環境を合わせる点で要件を満たしそうですし、知ってれば高速化の選択肢の一つになってたと思います。
現時点で自動化された結合テスト、E2Eテストはなく手動でカバーしている状況です😅
(自動化は検討しています)
ご返信ありがとうございますー!
理解しました。
またのご参加orご登壇、楽しみにしておりますー😆