• 카테고리

    질문 & 답변
  • 세부 분야

    백엔드

  • 해결 여부

    해결됨

강의 내용 중 testEntity 관련 질문입니다.

23.09.27 12:15 작성 23.09.27 12:16 수정 조회수 190

0

[질문 템플릿]
1. 강의 내용과 관련된 질문인가요? (예)
2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)
3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)

[질문 내용]
여기에 질문 내용을 남겨주세요.

 

@SpringBootTest
@Transactional
@Rollback(value = false)
class MemberTest {

@Autowired
 EntityManager em;

@Test
 public void testEntity() {
Team teamA = new Team("teamA");
Team teamB = new Team("teamB");

em.persist(teamA);
em.persist(teamB);

Member member1 = new Member("member1", 10, teamA);
Member member2 = new Member("member2", 20, teamA);
Member member3 = new Member("member3", 30, teamB);
Member member4 = new Member("member4", 40, teamB);

em.persist(member1);
em.persist(member2);
em.persist(member3);
em.persist(member4);

em.flush();
em.clear();

List<Member> members = em.createQuery("select m from Member m join fetch m.team", Member.class)
.getResultList();

assertThat(members.get(0).getTeam()).isEqualTo(teamA);
}
}

제가 작성한 테스트 코드는 위와 같습니다.

 

발생한 에러는

org.opentest4j.AssertionFailedError: 
expected: "Team(id=1, name=teamA) (Team@3ec52163)"
 but was: "Team(id=1, name=teamA) (Team@100d071)"
Expected :Team(id=1, name=teamA)
Actual   :Team(id=1, name=teamA)

위와 같습니다.

 

하나의 트랜잭션 안에서는 엔티티의 식별자가 같은 경우 ==비교를 하였을때 true라고 알고 있습니다.

따라서 저는 member1의 team(teamA)과 teamA를 isEqualTo로 비교하였을때 true가 나올것이라 예상하였지만 false가 나왔습니다. 에러 문구를 보면 객체 주소가 달라서 false가 나온것 같아 Team엔티티에 equalsAndHashCode 오버라이딩을 해주어도 false가 나옵니다.

물론 em.flush(), em.clear()를 하지 않고 영속성 컨텍스트에서 조회를 해오면 true가 나오는데 왜 영속성 컨텍스트를 초기화하고 DB에서 데이터를 가져오면 식별자가 같아도 같은 트랜잭션 내에서 ==비교가 true가 나오지 않는지 궁금합니다!

답변 2

·

답변을 작성해보세요.

1

David님의 프로필

David

2023.10.01

안녕하세요. kju2405님, 공식 서포터즈 David입니다.

  1. clear를 하게 되면, 조회시 새로운 객체가 생성됩니다.

  2. equals를 오버라이딩 하실 때, 식별자(id)를 비교하도록 수정하셔야 equals 비교를 통해 식별자만 같아도 동일한 객체로 인식합니다. 만약 별도의 비교 조건을 추가하지 않으셨다면 객체의 참조값으로 비교하게 됩니다. 따라서, 식별자가 같아도 clear 후 조회시 새로운 객체와 기존 객체의 참조값을 비교하게 되므로 false가 나옵니다.

감사합니다.

1

인프런 AI 인턴님의 프로필

인프런 AI 인턴

2023.09.29

안녕하세요, 인프런 AI 인턴이에요.

테스트 코드를 보면, 테스트 메서드에서 assertThat을 사용하여 members.get(0).getTeam() 값이 teamA와 일치하는지를 검증하려고 하고 있습니다. 하지만, 예상한 값과 실제 값이 동일한데도 AssertionFailedError가 발생했다는 것으로 보입니다.

AssertionFailedError는 테스트가 실패했음을 의미합니다. 이 에러는 assert 구문에서 예상한 값과 실제 값이 일치하지 않을 때 발생하는데, 왜 실패했는지에 대한 정보 역시 제공합니다.

에러 메시지를 보면, 예상한 값과 실제 값이 완전히 같아 보입니다. 하지만 오른쪽 괄호 뒤에 팀 객체의 해시 코드가 함께 출력되었는데, 이것이 예상한 값과 실제 값이 다르게 나온 이유입니다.

이 경우, Team 클래스의 toString() 메서드를 확인해 보세요. toString() 메서드가 객체의 해시 코드를 포함하여 값을 출력하는 경우, 해시 코드가 다르면 예상한 값과 실제 값이 일치하지 않다고 판단합니다.

따라서 Team 클래스의 toString() 메서드를 수정하여 해시 코드를 제외한 필요한 정보만을 출력하도록 수정하면 테스트가 정상적으로 통과할 것입니다.