TIL_031 | 테스트 코드 조금 더 우아하게 다루기

묘한묘랑·2024년 2월 19일
0

TIL

목록 보기
31/31

문제사항

Repository 테스트 코드를 작성하는데 마지막에 entityManager.flush를 해줘야지만 Query문이 보인다.
beforeTest에 DB에 직접 접근을 하면 Transaction 범위 내에서 사용하라고 말한다.

어떻게 해결하였는가?

1. 우선 Describe Spec의 it 내부에서 모든 작업이 다 이뤄져야 하는 상황이다.

그런데 it이 여러개일 경우, 우선 beforeTest를 이뤄내기 위해서는 코드 중복이 많이 일어날 것이다.
또한 실수로라도 마지막 줄에 flush가 없다면 query문이 보이지 않기 때문에 적어줘야 한다는 점이 매우 마음에 들지 않았다.
실수의 여지도 있으며, 보기에 썩 좋아보이지는 않았다.

2. 그럼 it을 확장시켜버리자!

말 그대로이다.
함수형 언어이므로 함수를 한번 더 감싸게 만들 수만 있다면 가능하다고 판단을 하고 시도를 해보았다.

3. 결과

typealias BeforeTest = () -> Unit

suspend fun DescribeSpecContainerScope.flushIt(
	name: String,
	em: TestEntityManager,
	beforeTest: BeforeTest? = null,
	test: suspend TestScope.() -> Unit
) {
	this.it(name) {
		beforeTest?.invoke()
		test.invoke(this)
		em.flush()
	}
}
describe(){
	context(){
		val beforeTest: BeforeTest = { doSomething... }
        flushIt("", entityManager, beforeTest){
        }
	}
}

entityManager를 주입을 필수로 해줘야하며, beforeTest의 경우 선택사항으로 두도록 만들었다.
결과적으로 it 내부에 있는 코드는 spec상의 요구와 맞게끔 작성할 수 있게 되었다.

생각해야 할 것

사실, 문제는 test마다 beforeTest가 돌아가기 때문에 context로 그것을 확장 시키고 싶지만 context에서는 transaction에서 벗어나있고, it에 주입할만한 방법이 떠오르지가 않는다.

profile
상황에 맞는 기술을 떠올리고 사용할 수 있는 개발자가 되고 싶은 개발자

0개의 댓글