AssertJ 테스트시 객체의 동등성(Equality) 검증 방법

2024. 4. 7. 15:11JAVA/JUNIT

 

배경

주식 포트폴리오 가상 관리 프로젝트(FineAnts)를 수행중 포트폴리오(Portfolio)라는 엔티티가 존재합니다. 포트폴리오 엔티티는 예산(Budget), 목표 수익 금액(TargetGain), 최대 손실 금액(MaximumLoss)라는 숫자형 데이터 타입을 필드 멤버로 가지고 있습니다. 기존에는 이 숫자형 데이터 타입을 Long 타입으로써 사용하고 있었고 테스트 코드 작성시 Long 타입의 데이터값을 전달하여 테스트를 검증하였습니다. 예를 들어 기존의 테스트 코드는 다음과 같았습니다.

Portfolio changePortfolio = portfolioRepository.findById(portfolioId).orElseThrow();
assertThat(changePortfolio)
    .extracting("name", "securitiesFirm", "budget", "targetGain", "maximumLoss")
    .containsExactly("내꿈은 워렌버핏", "미래에셋증권", 1500000L, 2000000L, 900000L);

위 코드를 변경 포트폴리오의 정보를 변경한 다음에 데이터베이스에서 변경된 포트폴리오를 다시 조회한 다음에 데이터가 정말로 변경되었는지 확인하는 코드입니다.

 

문제

포트폴리오 엔티티의 위 3가지 정보가 Long 타입에서 Money라는 타입으로 변경된 다음에 테스트 실행시 실패하였습니다. Money 클래스는 다음과 같습니다.

@Getter
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
public class Money implements Comparable<Money> {
	private final BigDecimal amount;

    // ...
}

 

테스트가 실패한 원인은 포트폴리오 엔티티 클래스의 budget, targetGain, maximumLoss 필드 멤버의 타입이 Money 타입으로 변경되어서 Long 타입과 비교가 불가능하기 때문입니다.

 

해결 방법

위와 같이 Money과 같은 커스텀 객체로 래핑된 타입을 AssertJ에서 비교하기 위해서 usingComparatorForType 메서드를 사용합니다. 해당 메서드를 사용하여 특정 클래스 타입의 비교 방법을 함수와 클래스 타입을 전달합니다.

assertThat(changePortfolio)
		.extracting(Portfolio::getName, Portfolio::getSecuritiesFirm, Portfolio::getBudget,
			Portfolio::getTargetGain, Portfolio::getMaximumLoss)
		.usingComparatorForType(Money::compareTo, Money.class)
        .containsExactly("내꿈은 워렌버핏", "미래에셋증권", Money.from(1500000L), Money.from(2000000L), Money.from(900000L));

참고로 extracting 메서드의 매개변수 전달이 위와 같이 함수형으로 전달할 수 있고, 아니면 필드 멤버명을 이전과 같이 문자열로 전달하여도 상관없습니다. 

 

그 다음에 containsExactly 메서드에 비교할 값을 전달할때 단순 Long 타입의 값을 전달하는 것이 아닌 동일한 클래스 타입인 Money 인스턴스로 만들어서 전달하면 Money 타입을 비교할때는 Money 클래스의 compareTo 메서드를 사용하여 비교할 것입니다. Money 클래스의 compareTo 메서드는 다음과 같습니다. compareTo를 재정의하기 위해서 Comparable 인터페이스를 상속받을 수 있습니다.

@Override
public int compareTo(Money m) {
    return this.amount.compareTo(m.amount);
}

 

 

References

https://stackoverflow.com/questions/63714635/assertj-fails-to-assert-bigdecimal-equality-without-scale

'JAVA > JUNIT' 카테고리의 다른 글

3.2 예외를 기대하는 세 가지 방법  (0) 2021.08.13
3.1 JUnit 단언  (0) 2021.08.13
2.1 JUNIT 테스트 고려사항 구현  (0) 2021.08.11
2. JUNIT 사용  (1) 2021.08.11
1. 첫번째 JUnit 테스트 만들기  (0) 2021.08.10