본문 바로가기
Spring

[Spring] 스프링 데이터 AbstractAggregateRoot 를 통해 도메인 이벤트 등록하고 테스트 하기

by 개발하는 지토 2021. 10. 31.

DDD 스터디중 구현해본 AbstractAggregateRoot를 통해 도메인 이벤트를 등록하고 테스트하는 방법을 간단하게만 정리함

(나중 참고용)

 

아직 깊은 지식이 없으므로 도메인 이벤트, AbstractAggregateRoot 에 대한 자세한 내용은 공식문서 & 타 블로그 정리 글을 참고하는 게 좋을 것 같음

 

https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/domain/AbstractAggregateRoot.html

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. -- 추 후에 발전 될 내용이 있으면 수정 필요

댓글