プロジェクト4

21341 ワード

複数のレポートを持つサービスをテストしますか?


昨日と今日、次のサービス方法をテストしてみました.
ショップを作成するときに、関連付けられたインスタンスを作成する方法を作成しました.
最初は上で学んだように、Mockを利用してテストできると思っていました.
@Service
@Transactional
@RequiredArgsConstructor
public class StoreCommandServiceImpl implements StoreCommandService {

    private final StoreRepository           storeRepository;
    private final EmployerRepository        employerRepository;
    private final JobOpeningRepository      jobOpeningRepository;
    private final PostManagementRepository  postManagementRepository;

    @Override
    public UUID create(UUID employerId, StoreCmdDto dto) {
        Employer employer = employerRepository.findById(employerId).orElseThrow();
        Store newStore = new Store(dto.getName(), dto.getAddress(), employer);
        Store saveStore = storeRepository.save(newStore);
        jobOpeningRepository.save(new JobOpening(newStore));
        postManagementRepository.save(new PostManagement(newStore));
        return saveStore.getId();
    }
}

ソリューション:移動またはSpringboot!


この問題を解決するためにMockを利用しようとしましたが、リポジトリに一致するオブジェクトを事前に作成する必要があります.
repoに対応するメソッドを呼び出すたびに、動作を指定する必要があります.
テストのために大量のコードを書く必要があるので、テストのためではなく、テストのためにコードを書くようです.Mockを使うコードも書いておいた方が良いのですが、Springboottestに変更してControl+Zを試してみましたが、リカバリの制限で代わりに言語を使います.
下記の添付資料を見てSpringbootsTestを使うことにしました.
    @Test
    public void createStore() throws Exception {
        //given
        Employer employer = new Employer("seouler",
                createAddress("seoul", "songpa", "42"));
        employerRepository.save(employer);
        StoreCmdDto storeCmdDto = new StoreCmdDto("starbucks",
                createAddress("busan", "gaepo", "24"));
        //when
        UUID uuid = storeCommandService.create(employer.getId(), storeCmdDto);
        //then
        Store findStore = storeRepository.findById(uuid).orElseThrow();
        JobOpening findJobOpening = jobOpeningRepository.findByStore(findStore).orElseThrow();
        PostManagement findPostManagement = postManagementRepository.findByStore(findStore).orElseThrow();
        assertEquals(findStore.getName(), storeCmdDto.getName());
        assertEquals(findStore.getAddress(), storeCmdDto.getAddress());
        assertEquals(findStore.getId(), findJobOpening.getStore().getId());
        assertEquals(findStore.getId(), findPostManagement.getStore().getId());
    }
関連関係外キー関係はstoreでcascadeを使って持続的な移行を使えばいいと思いますよね?ショップはJobOpeningとPostManagementの双方向操作は必要ないと思いますので、できませんでした.したがって、最終的には、サービスで別のrepoを呼び出すことでオブジェクトを作成し、保存します.Mockを使用して多くのオブジェクトを作成していないため、より短いコードでテストできます.
参考資料
ロックではなくSpringBootTestを選んだ理由
TDDフリーブックリンク

質問:repoを書きすぎたのではないでしょうか。


私の元の計画は、次のような関連関係を構築し、それに基づいて方法を作成することです.

テスト中に上記の問題を変更しましたが、これは正しい解決方法ではないと思います.
私は絵を描き始めましたが、上記の問題のようにrepoをたくさん使っているので、テストが難しいです.最初からデザインを間違えたのではないかと疑い始めました.
public class StoreCommandServiceImpl implements StoreCommandService {

    private final StoreRepository           storeRepository;
    private final EmployerRepository        employerRepository;
    private final JobOpeningRepository      jobOpeningRepository;
    private final PostManagementRepository  postManagementRepository;

    @Override
    public UUID create(UUID employerId, StoreCmdDto dto) {
        Employer employer = employerRepository.findById(employerId).orElseThrow();
        Store newStore = new Store(dto.getName(), dto.getAddress(), employer);
        Store saveStore = storeRepository.save(newStore);
        jobOpeningRepository.save(new JobOpening(newStore));
        postManagementRepository.save(new PostManagement(newStore));
        return saveStore.getId();
    }
}

解決:思考の基準を変える!


まず、PostManagementとJobOpeningの役割を組み合わせることができます.
そこで、両者を組み合わせてStoreManagementという新しいオブジェクトを作成しました.

私が最初にクライスを小さく分けたのは、私がすべての役を演じるべきだと思ったからです.
また,関連関係の主人はstoreではないため,save storeではcascade永続性遷移は利用できないと考えられる.したがって、多くのrepoを使用すると、新しいストレージオブジェクトを作成し、これらのオブジェクトを他のrepoに渡します.
長い間悩んでいましたが、StoreServiceに違いないと思いましたが、Storeは必ずしもストレージの主体ではありません.そこで,ストレージ管理を中心にコードを再設計した.
public class StoreCmdServiceImpl implements StoreCmdService {

    private final EmployerRepository        employerRepository;
    private final StoreManagementRepository storeManagementRepository;

    @Override
    public UUID create(UUID employerId, StoreCmdDto dto) {
        Employer employer = employerRepository.findById(employerId).orElseThrow();
        Store store = new Store(dto.getName(), dto.getAddress(), employer);
        StoreManagement storeManagement = new StoreManagement(store);
        storeManagementRepository.save(storeManagement);
        return store.getId();
    }
}
参考資料
[エレガントな技術セミナー]190425 TDD Refactoringby Java誌朴宰成