기존 커뮤니티 프로젝트에는 Service, Controller 레이어의 테스트밖에 없었습니다.
레거시 프로젝트를 리팩토링 작업을 하면서 기존 Service 레이어에서 사용한 Setter, Getter 조합을 도메인 메서드로 바꾸면서 테스트 할 것들이 생겼습니다.
Getter와 Setter의 사용이 최대한 제한되어 있는 상태에서 도메인 테스트 코드 작성을 진행해보겠습니다.
양이 너무 많다보니 예시로 하나만 업로드 하겠습니다.
오늘 예시로 사용될 도메인은 Message 도메인입니다. 먼저 도메인 코드를 확인해보겠습니다.
@Data
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
public class Message extends EntityDate {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Column(nullable = false)
private String title;
@Column(nullable = false)
private String content;
@Column(nullable = false)
private boolean deletedBySender;
@Column(nullable = false)
private boolean deletedByReceiver;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "sender_id")
@OnDelete(action = OnDeleteAction.NO_ACTION)
private User sender;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "receiver_id")
@OnDelete(action = OnDeleteAction.NO_ACTION)
private User receiver;
public Message(String title, String content, User sender, User receiver) {
this.title = title;
this.content = content;
this.sender = sender;
this.receiver = receiver;
this.deletedBySender = this.deletedByReceiver = false;
}
public void deleteBySender() {
this.deletedBySender = true;
}
public void deleteByReceiver() {
this.deletedByReceiver = true;
}
public boolean isDeletedMessage() {
return isDeletedByReceiver() && isDeletedBySender();
}
}
유저끼리 쪽지를 보낼 때 사용하는 Message 도메인입니다.
음 먼저 위에 @Data 어노테이션은 원래는 안 쓰는게 좋긴합니다만, 이 부분은 추후에 리팩토링 진행하겠습니다!
간단하게 도메인을 설명드리자면, 메시지 발신자와 수신자 모두 삭제를 해야 메시지가 삭제된다고 보면 되고 여기서 deleteBy~ 메서드는 삭제시 체킹해주는 부분입니다.
방금 @Data를 안 쓰는게 좋다고 했죠? 이 부분에서 안 써도 되는 이유는 isDeleteMessage() 메시지로 Getter가 없어도 상태를 확인할 수 없기 때문에 지워도 됩니다. (다만 저는 기존 다른 테스트에서 setter를 사용중이라 아직 제거하지는 못했습니다.)
우리는 이제 이 도메인 단위테스트를 진행하겠습니다.
package yoon.community.domain;
import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
import static yoon.community.factory.CreateMessageFactory.createMessage;
import static yoon.community.factory.UserFactory.createUser;
import static yoon.community.factory.UserFactory.createUser2;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import yoon.community.entity.message.Message;
import yoon.community.entity.user.User;
public class MessageTest {
User sender = createUser();
User receiver = createUser2();
@Test
@DisplayName("deleteBySender 테스트")
public void deleteBySenderTest() {
// given
Message message = createMessage(sender, receiver);
// when
message.deleteBySender();
// then
assertThat(message.isDeletedBySender()).isEqualTo(true);
}
@Test
@DisplayName("deleteByReceiver 테스트")
public void deleteByReceiverTest() {
// given
Message message = createMessage(sender, receiver);
// when
message.deleteByReceiver();
// then
assertThat(message.isDeletedByReceiver()).isEqualTo(true);
}
@Test
@DisplayName("메시지 삭제 테스트")
public void deleteMessageTest() {
// given
Message message = createMessage(sender, receiver);
// when
message.deleteByReceiver();
message.deleteBySender();
// then
assertThat(message.isDeletedMessage()).isEqualTo(true);
}
}
import 부분은 지우려고 했으나, 처음 하시는 분들은 어떤 것을 import할지 모를 수 있기 때문에 남겨두겠습니다.
위와 같이 저는 테스트 코드를 given, when, then 3단계로 나눠서 작성합니다.
컨트롤러와 서비스 레이어도 당연히 위와 같이 작성했고, 도메인도 마찬가지로 이렇게 작성해주었습니다.
1. given 부분은 테스트에 필요한 재료라고 보시면 되고
2. when 부분은 테스트에 필요한 작동이라고 보시면 되고
3. then 부분은 작동 후 테스트를 검증하기 위한 부분이라고 생각하시면 편합니다.
setter를 쓰지 않고 deleteBy~() 메서드로 도메인의 상태를 일관적으로 변경할 수 있고
getter를 굳이 쓰지 않아도 도메인 메서드인 isDeleteBy~() 메서드로 충분히 도메인의 상태를 확인할 수 있는 것을 알 수 있습니다.
이와 같이 지금까지 만든 도메인 메서드에서 할 수 있는 모든 단위 테스트를 만들어주었습니다.
이제 조금 더 완성도 있는 프로젝트 같나요?
테스트 코드를 작성해야하는 이유는 아래 링크를 통해 확인하실 수 있습니다.
https://blog.naver.com/sosow0212/222689055684
질문 및 피드백은 환영입니다 :)
https://github.com/sosow0212/community
'Project > Community' 카테고리의 다른 글
[커뮤니티 #18] Redis를 이용해서 포인트 랭킹 구현하기 (Sorted Set = ZSet) (0) | 2023.01.18 |
---|---|
[커뮤니티 #17] 기본 키 타입, 네이밍 리팩토링 작업 (0) | 2023.01.01 |
[커뮤니티 #15] 클린코드 리팩토링 (Admin API) / 도메인 메서드를 사용하는 이유 (1) | 2022.12.26 |
[커뮤니티 #14] 기존 커뮤니티 프로젝트 클린코드 리팩토링 (Comment, Report) (0) | 2022.12.21 |
[커뮤니티 #13] 기존 프로젝트 리팩토링 계획 및 진행하기 (0) | 2022.11.23 |