【Java】【AWS】staticなAmazonS3をmock

Java
  • AmazonS3がstaticなフィールドとして設定されている
  • そのフィールドを呼ぶメソッドをテストしたい
    のケースがあり、試行錯誤したのでメモ
  • ケースバイケースだが、テスト元をリファクタリングをした方が良いケースもありそう

やったこと

  • AmazonS3クラスでbucketを作成するメソッド
    • 既存バケットがある場合は作成しない
  • テストコードは作成する場合、作成しない場合を両方テスト
    • カバレッジ率が100%になることを確認する
  • staticなフィールドを設定するためにリフレクションを使用した

サンプルコードと実行結果

サンプルコード

  • テスト対象コード
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.Bucket;

public class s3UseClass {

    // 今ここのmock化を検証したいので、nullにしておく
    private static AmazonS3 client = null;

    public static boolean createBucket(String bucketName){
        if (client.doesBucketExistV2(bucketName)) {
            System.out.println("パターンfalse");
            System.out.println("doesBucketExistV2");
            System.out.println();
            return false;
        }
        Bucket bucket = client.createBucket(bucketName);
        System.out.println("パターンtrue");
        System.out.println(bucket.toString());
        System.out.println(client.getBucketLocation(bucketName));
        System.out.println();
        return true;
    }
}
  • テストコード
    • createBucketTrueTest → バケットが作成される場合のテスト
    • createBucketFalseTest → バケットが作成されない場合のテスト
    • initCreateBucketTestでバケット作成される場合、されない場合の両方で使用する処理の用意
    • BucketS3Clientのmockの用意
    • テスト対象メソッドで呼び出すs3Clientのフィールドの用意
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.Bucket;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.lang.reflect.Field;

import static org.mockito.Mockito.*;

public class s3UseClassTest {
    private String bucketName;
    private String bucketLocation;
    private AmazonS3 client;
    private Bucket bucket;

    @BeforeEach
    void initCreateBucketTest() throws NoSuchFieldException, IllegalAccessException {
        bucketName = "testBucketName";
        bucketLocation = "testBucketLocation";

        //mock化の宣言
        client = mock(AmazonS3.class);
        // bucketのmock宣言
        bucket = mock(Bucket.class);

        // field値の設定
        // staticフィールド"client"を設定
        // 設定用インスタンスの生成
        s3UseClass testS3UseClass = new s3UseClass();
        // フィールド値の設定
        Field testClient = s3UseClass.class.getDeclaredField("client");
        testClient.setAccessible(true);
        testClient.set(testS3UseClass, client);
    }

    @Test
    void createBucketTrueTest() throws NoSuchFieldException, IllegalAccessException {

        // AmazonS3のmock定義
        when(client.doesBucketExistV2(bucketName)).thenReturn(false);
        when(client.createBucket(bucketName)).thenReturn(bucket);
        when(client.getBucketLocation(bucketName)).thenReturn(bucketLocation);

        // テスト対象メソッドを呼び出し
        boolean checkResult = s3UseClass.createBucket(bucketName);

        // ↑での定義したメソッドが呼ばれているか確認
        verify(client, times(1)).doesBucketExistV2(bucketName);
        verify(client, times(1)).createBucket(bucketName);
        verify(client, times(1)).getBucketLocation(bucketName);

        // 返り値がtrueであることを確認
        Assertions.assertTrue(checkResult);
    }

    @Test
    void createBucketFalseTest() throws NoSuchFieldException, IllegalAccessException {
        // AmazonS3のmock定義
        when(client.doesBucketExistV2(bucketName)).thenReturn(true);

        // テスト対象メソッドを呼び出し
        boolean checkResult = s3UseClass.createBucket(bucketName);

        // ↑での定義したメソッドが呼ばれているかと、呼ばれていないことを確認
        verify(client, times(1)).doesBucketExistV2(bucketName);
        verify(client, times(0)).createBucket(bucketName);
        verify(client, times(0)).getBucketLocation(bucketName);

        // 返り値がFalseであることを確認
        Assertions.assertFalse(checkResult);

    }
}

実行結果

  • 実行がTrueパターンとFalseパターンに分かれて出力されることを確認
    • Trueパターンでは
    • bucket情報が表示されること
    • backetの場所がmockで指定した内容
    • Falseパターンでは
    • doesBucketExistV2と表示されること

  • テストが2件passしていること
  • カバレッジが100%
    を確認

参考

コメント

タイトルとURLをコピーしました