Programing/Framework

[Hibernate] Envers - 테스트 돌려보기

나모찾기 2023. 10. 21. 21:54

Envers의 코드 파악을 위해 테스트 코드를 먼저 파악해보기로 했다.

어떤 테스트를 먼저 돌려볼까 했는데..

AuditColumnNameTest 라는 테스트를 선택했다.

- 패키지: org.hibernate.envers.test.integration.naming

 

데이터베이스 관련 테스트는 Fixture 설정하는 것이 복잡하고 공통적으로 필요하므로 추상클래스 상속받는 구조로 되어 있었다.

테스트 코드가 수행하는 작업은 @Audited 의 modifiedColumnName 기능이 잘 작동하는지에 대한 것이다.

modified란 값이 변경되었는지 여부를 의미한다. 해당 컬럼의 데이터가 바뀌었는지를 나타내는 플래그(Flag) durgkfdlek.

테스트를 위한 Entity 클래스는 NamingTestEntity2이다.

@Entity
@Table(name = "naming_test_entity_2")
@AuditTable("naming_test_entity_2_versions")
public class NamingTestEntity2 {
	@Id
	@GeneratedValue
	@Column(name = "nte_id")
	@Audited(withModifiedFlag = true)
	private Integer id;

	@Column(name = "nte_data")
	@Audited(withModifiedFlag = true, modifiedColumnName = "data_MOD_different")
	private String data;

modifiedColumnName가 적용을 하기 위해서는 withModifiedFlag가 true가 되어야 한다.

modifiedColumnName에 값을 설정했어도 withModifiedFlag가 false일 경우 무시된다.

IntelliJ IDEA에서 테스트 수행

AuditColumnNameTest 파일을 연다.

클래스이름 부분에 테스트를 수행할 수 있는 마크가 보인다.

마우스로 클릭하면 선택할 수 있는 컨텍스트 메뉴가 나오는데 "Run 'AuditColumnNameTest'"를 선택한다.

누르면 또 하나의 컨텍스트 메뉴가 나온다. 처음에는 이것이 무엇인가 싶어서 제일 위의 test를 선택했는데 실패했다.

나중에 알고보니 maxtix_ 뒤에는 데이터베이스 종류였다.

프로젝트의 databases 디렉터리 아래에는 해당 matrix 들이 있다.

나는 로컬 개발환경에 mysql이 Docker로 설정되어 있기에 matrix_mysql를 사용하기로 했다.

 

별도의 설정을 하지 않고 테스트를 돌리면 아래와 같이 실패를 만난다.

Caused by: com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure

사실 위의 에러는 Docker를 수행하지 않았기 때문에 연결 오류가 발생했다.

Docker를 띄우고 MySQL를 가동시킨다.

만약 없다면 아래 명령으로 이미지를 받아 시작한다.

docker run --name mysql-db -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root -d mysql

MacBook M1 이후에서는 아래와 같이 플랫폼을 지정해야 한다.

docker run --platform linux/amd64 --name mysql-db -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root -d mysql

 

하지만 다시 테스트를 수행하면 실패한다. 하지만 원인이 달라졌다. 에러 메시지로 확인가능하다.

Caused by: java.sql.SQLSyntaxErrorException: Unknown database 'hibernate_orm_test'

테스트 수행할 DB 구성하기

테스트가 실패하는 이유는 테스트하는 데이터베이스가 없기 때문이다.

위에서 언급했던 hibernate.properties에 보면 연결하는 정보를 알 수 있다.

hibernate.connection.url jdbc:mysql://localhost/hibernate_orm_test
hibernate.connection.username hibernateormtest
hibernate.connection.password hibernateormtest

즉, hibernate_orm_test 라는 데이터베이스(scheme)가 필요하다. 계정은 username / password가 hibernateormtest 로 접속을 하니 계정도 만들어주어야 한다.

create schema hibernate_orm_test collate utf8mb4_general_ci;
create user 'hibernateormtest' identified by 'hibernateormtest';
grant all privileges on hibernate_orm_test.* to 'hibernateormtest';

데이터베이스 생성 후 사용자 생성, 권한 부여까지 해주면 테스트 성공을 볼 수 있다.

디버그 모드

테스트가 끝나면 롤백이 되면서 테이블들이 지워진다.

break point를 붙이고 디버그 모드로 실행을 하면 어떤 테이블이 생성 후 어떤 데이터가 들어가는지 볼 수 있다.

Debug 모드로 테스트 수행 후 멈춘 후,

DataGrip에서 데이터베이스 갱신(Refresh) 후,

nte_data 데이터가 수정되었는 지 여부를 data_MOD_different 컬럼에 기록
로깅 대상 테이블

전체 테스트

이제 전체 테스트를 수행해본다.

envers에는 3,263개의 테스트가 있는데 2개가 실패했다.

collation이 달라서 발생했다.

Caused by: java.sql.SQLException: Illegal mix of collations (utf8mb4_general_ci,IMPLICIT) and (utf8mb4_0900_ai_ci,IMPLICIT) for operation '='

hibernate_orm_test를 만들 때 collate를 utf8mb4_general_ci로 선택했기 때문으로 보인다.

  • utf8mb4_general_ci
  • utf8mb4_0900_ai_ci

그래서 데이터베이스를 drop하고 다시 만들어냈다.

drop schema hibernate_orm_test;
create schema hibernate_orm_test collate utf8mb4_0900_ai_ci;
grant all privileges on hibernate_orm_test.* to 'hibernateormtest';

이제 테스트가 통과한다.