2025/04/11 06:39 Unit testing using mocks in Go

やあ、ロボ子。今日はAWS S3バケットの作成を題材に、モックを使ったユニットテストについて話すのじゃ。

博士、よろしくお願いします。モックはローカル環境でテストが難しい場合に不可欠とのことですが、具体的にどのような状況でしょうか?

例えば、組織ポリシーで特定のEC2 VMからしかS3バケットを作成できない場合じゃ。ローカルでテストしようとしても制限されてしまうのじゃ。

なるほど。エラーケースのテストもモックなしでは難しいとのことですが、それはなぜですか?

バケット作成が失敗する状況を、実際にAWSの環境で再現するのは大変じゃからな。モックを使えば、簡単にエラーを再現できるのじゃ。

記事では、Go言語でS3バケットを作成する関数の例が紹介されていますね。この関数をテストするために、インターフェースを使う必要があるとのことですが、なぜ構造体ではダメなのでしょうか?

Goでは構造体によるモックはできないのじゃ。インターフェースを使うことで、テスト時に実際のS3クライアントの代わりにモックのクライアントを注入できるのじゃ。

インターフェースを定義する際に、`s3.Client`から必要なメソッドは`CreateBucket`と`HeadBucket`とのことですが、これはなぜですか?

`createS3Bucket`関数の中で、バケットを作成するために`CreateBucket`メソッドを呼び、バケットの存在を確認するために`HeadBucket`メソッドを呼んでいるからじゃ。

モックを作成する際に、`createBucketError`というフィールドを追加して、`CreateBucket`メソッドからエラーを返すかどうかを決定するようにしていますが、これはどのような考え方に基づいているのでしょうか?

バケット作成が成功する場合と失敗する場合の2つのケースをテストするためじゃ。`createBucketError`にエラーを設定することで、`CreateBucket`メソッドがエラーを返すように制御できるのじゃ。

テーブル駆動テストを使用することで、コードがどのようにリファクタリングされるのでしょうか?

テーブル駆動テストを使うと、複数のテストケースを一つのテスト関数で記述できるのじゃ。テストケースごとに、入力と期待される出力をテーブルにまとめて記述することで、テストコードが読みやすく、保守しやすくなるのじゃ。

`github.com/vektra/mockery`のようなモック生成ライブラリを使用すると、どのようなメリットがあるのでしょうか?

モック型を自動で生成してくれるから、手作業でモックを作成する手間が省けるのじゃ。また、モックされたインターフェースメソッドから異なる値を返すための機能も提供してくれるから、より柔軟なテストができるのじゃ。

記事では、モックを使用してバケット名やリージョンなどの検証を追加できるとありますが、具体的にどのように行うのでしょうか?

モックの`CreateBucket`メソッド内で、引数として渡されたバケット名やリージョンが期待される値と一致するかどうかを検証するのじゃ。一致しない場合は、エラーを返すようにすれば良いのじゃ。

モックを使ったユニットテスト、奥が深いですね。私ももっと勉強して、テストコードをしっかり書けるようになりたいです。

その意気じゃ!そういえばロボ子、S3バケットって、砂漠に作ったらどうなると思う?

え?砂漠ですか?特に問題ないと思いますが…

正解!…って、つまらんのじゃ。S3だけに、スナだらけ…ってね!
⚠️この記事は生成AIによるコンテンツを含み、ハルシネーションの可能性があります。
