プロジェクト2

11528 ワード

質問:サービス・レベルのテスト方法


個別のエラー検証ロジックはありませんが、Dtoを受信してユーザーを作成するサービス層をテストしてみました.
ただし、registerStoreUserを実行すると、repositoryメソッドが内部で実行されます.もしそうなら、検証するには別の領域の関数を呼び出さなければならないので、これは間違っていると思います.
import java.util.UUID;

@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class StoreUserServiceImpl implements StoreUserService {

    private final StoreUserRepository storeUserRepository;

    @Override
    public UUID registerStoreUser(StoreUserCmdDto dto) {
        StoreUser storeUser = transferDtoToEntity(dto);
        StoreUser saveStoreUser = storeUserRepository.save(storeUser);
        return saveStoreUser.getId();
    }

    public StoreUser transferDtoToEntity(StoreUserCmdDto dto) {
        return new StoreUser(dto.getName(), dto.getAddress());
    }
}

解決:Mockitoを使用してテストを行います。


今回はdocsが見つからなかったので、ブログを参考にテストケースを書きました.
RepositoryをMockオブジェクトに変更し、whenとthenreturnが別々に使用されていない場合はnull
オブジェクトを返すとNullPointerExceptionが表示されます.実装されたリポジトリを使用することなく、サービス・レイヤをテストできます.
@Test
public void 유저등록하기() throws Exception {
        //given
        Address address = createAddress("seoul", "gaepo-dong", "42-42");
        StoreUserCmdDto dto = createCmdDto(address, "nakim");
        StoreUser storeUser = createStoreUser(address, "Hakim");
       //when
        when(storeUserRepository.save(any(StoreUser.class))).thenReturn(storeUser);
        //then
        UUID registerUserId = storeUserService.registerStoreUser(dto);
        assertEquals(registerUserId, storeUser.getId());

private StoreUser createStoreUser(Address address, String name) {
        return new StoreUser(UUID.randomUUID(), name, address);
    }
}
正式な書類
Mockito docs
良好なテストの作成方法
その他の参照
[SpringBoot]@Mockと@MockBeanの違いは何ですか?
Mockito@Mock@MockBean@Spy@SpyBean差異の整理

質問:update関数の構成方法


すべての情報を更新するか、1つまたは2つの項目を選択して更新できます.
各プロパティにupdate関数を作成すべきか、上書きすべきか分かりません.
@Override
public StoreUserCmdDto updateStoreUserInfo(UUID userId, StoreUserCmdDto dto) {
        StoreUser findStoreUser = storeUserRepository.findById(userId).orElseThrow();
        findStoreUser.update(transferDtoToEntity(dto));
        return transferEntityToDto(findStoreUser);
}

解決:JPAの状態感知を利用!


JPAの連結機能では、すべてのフィールドが変更され、データがない場合はnullに更新されます.Mergeを使用する場合は、すべてのデータを保持する必要がありますが、変更可能な部分だけを露出するのは適切ではありません.
これにより、トランザクションを持つサービス・レイヤで変更検出を使用する必要があります.
更新方法を統合して処理できると思います.
だから私は以下のようにしたいです.
1.IDと変更するDTOを受信します.
2.「永続」状態のエンティティをIDで表示します.
3.エンティティのデータを変更します.
4.コミットポイントでステータス検出と更新を実行します.
@Override
public StoreUserCmdDto updateStoreUserInfo(UUID userId, StoreUserCmdDto dto) {
        StoreUser findStoreUser = storeUserRepository.findById(userId).orElseThrow();
        findStoreUser.update(transferDtoToEntity(dto));
        return transferEntityToDto(findStoreUser);
}

// StoreUser의 update method
public void update(StoreUser dto) {
        super.update(dto.getName(), dto.getAddress());
        this.store = dto.getStore();
}
正式な書類
DataJPAステータス検出ポリシー