なぜ、モックが必要か?
主に自分のアプリから外部APIを呼び出すときに、外部APIの呼び出し箇所だけ仮の動作をさせたいときにモックを使用します。
SpringBootのJUnitでモックを使用する方法
方法 | メリット | デメリット |
モックオブジェクトを作成して、DIする | コードでモックの挙動を制御できるため、自由度が高い。 | |
Mockit等のモックライブラリを作成する | モックライブラリの使用方法を学習する必要がある。 | |
wiremockなどモックサーバを立てる |
モックオブジェクトを作成して、DIする
サンプルコード
1.テスト対象クラス
@Service
public class LoginServiceImpl implements LoginService {
private final S3Accessor s3Accessor;
public LoginServiceImpl(S3Accessor s3Accessor) {
this.s3Accessor = s3Accessor;
}
@Override
public String login(String mail, String password) {
String s3get = s3Accessor.get(mail, password);
return s3get;
}
}
コンストラクタインジェクションによりDIするようにしておきます。
S3Accessorは適当なのですが、DaoやRepositoryでも同様に、コンストラクタでインスタンスを受け取るようにしておくのがポイントです。
2.モック
public class S3AccessorImplMock implements S3Accessor {
@Override
public String get(String dir, String fileName) {
return "this is mock";
}
}
S3Accessorの実装クラスをS3AccessorImplクラスとして作成したので、ここではS3AccessorImplMockクラスを定義しています。
Javaコードなので、引数の値に応じて自由にモックの挙動を変えることができます。
3.テストコード
@SpringBootTest
public class LoginServiceImplTest {
@Test
public void login1() {
var s3Accessor = new S3AccessorImpl(); // 実装クラスをそのまま使う
var loginServiceImpl = new LoginServiceImpl(s3Accessor);
String login = loginServiceImpl.login("foo", "bar");
// test code
}
@Test
public void login2() {
var s3Accessor = new S3AccessorImplMock(); // モックを使う
var loginServiceImpl = new LoginServiceImpl(s3Accessor);
String login = loginServiceImpl.login("foo", "bar");
// test code
}
}
モックを使う場合は、login2のようにLoginServiceImplに渡すs3Accessorの中身をモッククラスにしてあげれば良いです。