DDD 스터디중 구현해본 AbstractAggregateRoot를 통해 도메인 이벤트를 등록하고 테스트하는 방법을 간단하게만 정리함
(나중 참고용)
아직 깊은 지식이 없으므로 도메인 이벤트, AbstractAggregateRoot 에 대한 자세한 내용은 공식문서 & 타 블로그 정리 글을 참고하는 게 좋을 것 같음
https://www.baeldung.com/spring-data-ddd
https://daddyprogrammer.org/post/14797/springboot-domainevent/
도메인 이벤트 등록
Entity가 AbstractAggregateRoot 를 상속하여 이벤트 등록이 가능하도록 함
@Entity
public class WishList extends AbstractAggregateRoot<WishList> {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private Long memberId;
@OneToMany
private final List<Lecture> lectures = new ArrayList<>();
private boolean active;
... ...
}
AbstractAggregateRoot을 상속하면 registerEvent(T event) 메서드를 통해 간단히 이벤트를 등록 할 수 있음
// WishList 클래스의 add 메서드 : 위시 리스트에 강의를 추가하면 Cart(수강바구니)에서는 해당 강의를 삭제해주기 위한 이벤트 등록
public void add(Lecture lecture) {
if (lectures.contains(lecture)) {
throw new IllegalArgumentException("중복된 강의는 추가할 수 없다.");
}
lectures.add(lecture);
log.info("publish CartInLectureRemovedEvent");
registerEvent(new CartInLectureRemovedEvent(lecture, memberId));
}
EventListener에서는 단지 등록한 이벤트와 같은 타입의 클래스를 받아주기만 하면 이벤트 register - listen을 구현할 수 있음 (해당 클래스는 도메인 서비스로 정의함)
@Slf4j
@RequiredArgsConstructor
@DomainService
public class CartInLectureRemovedEventListener {
private final CartRepository cartRepository;
@Async
@EventListener
@Transactional
public void listen(CartInLectureRemovedEvent cartInLectureRemovedEvent) {
log.info("Listen CartInLectureRemovedEvent");
Cart cart = cartRepository.findByMemberId(cartInLectureRemovedEvent.getMemberId());
cart.removeByEvent(cartInLectureRemovedEvent.getLecture());
}
}
이벤트 등록 테스트 작성 - 이게 맞는지 모르겠음, 좋은 방법이 있다면 알려주세용 :)
AbstractAggregateRoot를 상속한 엔티티 테스트 시 페이크 객체를 만들어서 테스트 진행
- class WishListTest
@DisplayName("강의를 추가시 수강바구니에서 해당 강의를 삭제하는 이벤트를 발행한다.")
@Test
public void publishEventByAddLecture() {
// given
FakeWishList wishList = WishListFixture.페이크_위시리스트();
// when
wishList.add(LectureFixture.승인_완료된_강의());
// then
assertThat(wishList.isRegist()).isTrue();
}
- class WishListFixture
public class WishListFixture {
public static FakeWishList 페이크_위시리스트() {
return new FakeWishList();
}
}
- class FakeWishList
@Getter
public class FakeWishList extends WishList{
private boolean regist;
@Override
protected <PublishedEvent> PublishedEvent registerEvent(PublishedEvent event) {
this.regist = true;
return super.registerEvent(event);
}
}
결론: 도메인 이벤트를 통해 다른 애그리거트로 정의한 도메인과의 결합도를 낮춤
// 2021 10 31. -- 추 후에 발전 될 내용이 있으면 수정 필요
댓글