0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[リサーチ・メモ]@ParameterizedTestとjsonを使用してパラメータ化テストを行う

Posted at

依存関係を追加

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.12.3</version>
</dependency>

※<scope>test</scope>にするとjackson-databindがtestでしか使用できなくなりObjectMapperが使えなくなる為注意する

テスト対象

@Service
public class NewMemberRegistrationServiceImpl implements NewMemberRegistrationService {

	@Autowired
	private NewMemberRegistrationMapper newMemberRegistrationMapper;

	@Autowired
	private BCryptPasswordEncoder bCryptPasswordEncoder;

	@Autowired
	private Properties properties;

	/**
	 * 新規会員登録
	 * 
	 * @param memberInfo 会員情報
	 * @throws IOException ファイルから変数取得失敗
	 */
	@Override
	public void newMemberRegistration(MemberInfo memberInfo) throws IOException {

		// 重複チェック
		if (newMemberRegistrationMapper.duplicationCheck(memberInfo.getEmail()) != 0) {
			throw new DuplicationCheckException(memberInfo.getEmail());
		}

		// USER権限を付与
		properties.load(new FileInputStream("src/main/resources/application.properties"));
		String memberAuthority = properties.getProperty("MEMBER_AUTHORITY_USER");
		memberInfo.setAuthority(memberAuthority);

		// パスワードハッシュ化
		memberInfo.setPassword(bCryptPasswordEncoder.encode(memberInfo.getPassword()));

		newMemberRegistrationMapper.newMemberRegistration(memberInfo);
	}

	public class DuplicationCheckException extends RuntimeException {
		public DuplicationCheckException(String email) {
			super("メールアドレスが重複しています: " + email);
		}
	}

}

テストパラメータの準備

@Data
public class TestParams {

	// テスト名
	public String testName;

	// リクエストの会員情報
	public MemberInfo memberInfoRequest;

	// 検証結果用の会員情報のレスポンス
	public MemberInfo memberInfoResponse;

	// リクエストのメールアドレス
	public String email;

	// 検証結果用の会員情報のレスポンス
	public int duplicationCheckResponse;

}

テストパラメータのオブジェクト準備

[
    {
        "testName": "正常系:新規会員登録チェック",
        "memberInfoRequest": {
            "memberID": null,
            "lastName": "姓",
            "firstName": "名",
            "email": "1234@test.com",
            "phoneNumber": "0123456789",
            "age": "18",
            "gender": "男性",
            "password": "password",
            "authority": "USER",
            "created_at": null,
            "update_at": null
        },
        "memberInfoResponse": {
            "memberID": 3,
            "lastName": "姓",
            "firstName": "名",
            "email": "1234@test.com",
            "phoneNumber": "0123456789",
            "age": "18",
            "gender": "男性",
            "password": "hashedPassword",
            "authority": "USER",
            "created_at": "CURRENT_TIMESTAMP",
            "update_at": null
        },
        "email": "test@test.com",
        "duplicationCheckResponse": 0
    },
    {
        "testName": "正常系:重複チェック 重複なし",
        "memberInfoRequest": null,
        "memberInfoResponse": null,
        "email": "test@test.com",
        "duplicationCheckResponse": 0
    },
    {
        "testName": "正常系:重複チェック 重複あり",
        "memberInfoRequest": null,
        "memberInfoResponse": null,
        "email": "user@test.com",
        "duplicationCheckResponse": 1
    }
]

テストの作成

@SpringBootTest
public class NewMemberRegistrationServiceImplTest {

	@InjectMocks
	private NewMemberRegistrationServiceImpl service;

	@Mock
	private NewMemberRegistrationMapper newMemberRegistrationMapper;

	@Mock
	private BCryptPasswordEncoder bCryptPasswordEncoder;

	@Mock
	private Properties properties;

	public static Stream<TestParams> provideTestParameters() throws Exception {
		ObjectMapper objectMapper = new ObjectMapper();
		// JSONファイルのパスを指定
		String jsonFilePath = "テストデータのjsonパス";

		// JSONファイルからTestParamsオブジェクトのリストを読み込む
		List<TestParams> testParamList = objectMapper.readValue(Paths.get(jsonFilePath).toFile(),
				new TypeReference<List<TestParams>>() {
				});

		// リストをStreamに変換して返す
		return testParamList.stream();
	}

	@ParameterizedTest(name = "{0}")
	@MethodSource("provideTestParameters")
	public void testWithParameters(TestParams params) {

		try {
			when(newMemberRegistrationMapper.duplicationCheck(anyString())).thenReturn(params.duplicationCheckResponse);
			when(bCryptPasswordEncoder.encode(anyString())).thenReturn("hashedPassword");

			if (params.testName.equals("エラー系:環境変数ファイルの取得、ファイルの読み込みエラー")) {
				doThrow(new IOException()).when(properties).load(any(FileInputStream.class));
			} else {
				when(properties.getProperty("MEMBER_AUTHORITY_USER")).thenReturn("USER");
			}

			// 検証対象のメソッドを呼び出す
			service.newMemberRegistration(params.memberInfoRequest);

			// newMemberRegistrationMapperリクエストをキャプチャする
			ArgumentCaptor<MemberInfo> memberInfoArgumentCaptor = ArgumentCaptor.forClass(MemberInfo.class);
			verify(newMemberRegistrationMapper).newMemberRegistration(memberInfoArgumentCaptor.capture());

			// newMemberRegistrationMapperリクエストの整合性を検証する
			MemberInfo capturedMemberInfo = memberInfoArgumentCaptor.getValue();
			assertEquals(params.memberInfoResponse, capturedMemberInfo);

			// 例外が発生するテストケースがオーバーランしないことを確認する
			if (params.resultExceptionName != null) {
				fail("例外が発生していない");
			}
		} catch (Exception e) {
			// キャッチした例外の検証
			if (params.resultExceptionName != null) {

				// 例外が発生するテストケースで想定した例外が発生したことを確認する
				assertEquals(e.getClass().getName(), (params.resultExceptionName));
			} else {
				// 例外が発生しないテストケースで想定外の例外が発生しないことを確認する
				fail("例外が発生している");
			}
		}

	}
}
アノテーション 内容
@SpringBootTest DIを動作させる為に付与する
@InjectMocks テスト対象に付与する
@Mock モック化する為に、テスト対象外に付与する
@ParameterizedTest(name = "{0}") 異なるjsonパラメータを使用して同じテストを行う為に付与する
junit実行後にテスト名を表示させる為にnameを指定する
※実行結果参照
@MethodSource("provideTestParameters") 上記とセットで使用し、引数にjsonデータを返すメソッドを指定する

※実行結果
image.png

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?