본문 바로가기
쿤즈 Dev/Spring Boot

[Spring Boot] Repository 테스트 코드 작성하기(feat. Kotlin)

by :)Koon 2022. 6. 4.

스프링 부트 프로젝트를 진행하면서 이제는 선택이 아닌 필수가 되는 것 중 하나가 바로 테스트 코드의 작성입니다. 테스트 코드는 무작정 작성해도 되지만 잘 작성해 놓으면 여러 가지 오류에 대해서 대처가 가능합니다.

이번 포스팅에서는 Repository를 만들고 테스트 하는 방법에 대해서 알아볼게요.


JPA를 이용해 Repository 만들기

레포 테스트를 위해서는 우선 클래스를 만들어야 합니다. JPA를 이용하면 이러한 Repository 클래스들을 손쉽게 만들고 CRUD가 가능합니다. 먼저 회원 Entity를 만들어 보겠습니다.

@Entity
class Member(
    var name: String,
    var age: Int,
) {
    @Id
    @GeneratedValue
    @Column(name = "member_id")
    val id: Long? = null
}

이렇게 회원 엔티티가 만들어지면 스프링부트 프로젝트를 실행해봅니다. 정상적이라면 데이터베이스에 member라는 테이블이 생성되고 내부 필드에 member_id, name, age가 생성됩니다.

 

그렇다면 이제 레포지토리를 만들어 볼게요.

interface MemberRepository: JpaRepository<Member, Long>{
    fun findByName(name: String): Optional<Member>
}

JPA를 사용하면 레포지토리 생성이 매우 간단합니다. JpaRepository를 상속받아서 MemberRepository를 인터페이스로 만들어 두었습니다. JpaRepository는 다음과 같은 기능들이 이미 구현이 되어 있습니다.

기본적인 find 함수들부터 저장, 삭제기능들이 구성이 되어 있기 때문에 추가 구현을 할 필요가 없습니다. 저는 추가적으로 name이라는 이름으로 검색하는 함수를 만들었습니다. 이 역시 구현체 없이 함수만 있어도 기능이 구현됩니다. JPA의 특징이죠.

 

이제 테스트를 할 준비가 다 되었기 때문에 테스트를 진행해 보도록 하겠습니다.


SpringBoot Repository 테스트

테스트 코드를 만들기 위해서는 스프링부트 프로젝트의 test 패키지로 이동합니다. 그리고 테스트 프로그램을 만들어 보도록 하겠습니다.

@SpringBootTest
@Transactional
class MemberRepositoryTest(
    @Autowired val memberRepository: MemberRepository
) {

    @Test
    @DisplayName("회원 저장 성공")
    fun `member save`()
    {
        //given
        val member = Member("koon", 30)

        //when
        val savedMember = memberRepository.save(member)

        //then
        assertEquals(savedMember.id, member.id)
        assertEquals(savedMember.name, member.name)
    }
}

 

테스트 코드의 기본은 given, when, then입니다. 무엇을 줄지, 무엇을 테스트하고, 어떤 결과를 받을지가 필요합니다.

 

@Transactional을 사용하는 이유는 Rollback입니다. 테스트 코드의 경우는 실제 운영하는 DB에 테스트도 하지 않으면서도 테스트 DB에 연결한다 하더라도 테스트 데이트가 반복적으로 입력되면 문제가 되기 때문이죠. 그래서 테스트를 진행하고 Rollback을 하도록 애노테이션을 사용합니다.

 

@Autowired 애노테이션은 테스트코드에서 사용하는 애노테이션으로 스프링에서는 주입(DI) 구조를 많이 사용하지만 실제 코드에서는 @Autowired 보다는 생성자 주입 코드를 주로 이용합니다. 하지만 테스트 코드에서는 @Autowired 애노테이션을 사용해서 주입할 클래스를 미리 주입하여 생성합니다.

 

테스트 함수를 만들기 위해서는 @Test 애노테이션을 이용합니다. 그리고 이 애노테이션 내에 테스트할 내용을 given, when, then 형식으로 입력해줍니다.

 

위 테스트는 회원을 만들고 저장하고 정상적으로 저장이 되었다면 저장된 값이 내가 저장한 값과 일치하는지 확인합니다.


내가 만든 Repository 함수 테스트

이번에는 위에서 Repository에 만든 함수를 테스트해보도록 하겠습니다. 

@SpringBootTest
@Transactional
class MemberRepositoryTest(
    @Autowired val memberRepository: MemberRepository
) {

    @Test
    @DisplayName("회원 저장 성공")
    fun `member save`()
    {
        //given
        val member = Member("koon", 30)

        //when
        val savedMember = memberRepository.save(member)

        //then
        assertEquals(savedMember.id, member.id)
        assertEquals(savedMember.name, member.name)
    }

    @Test
    @DisplayName("회원 Id 조회")
    fun `member find by id`() {
        // given
        val member = Member("koon", 30)
        memberRepository.save(member)

        // when
        val findMember = memberRepository.findById(member.id!!)
            .orElseThrow { IllegalStateException("Member not found.") }

        // then
        assertEquals(findMember.id, member.id)
        assertEquals(findMember.name, member.name)
    }

    @Test
    @DisplayName("회원 이름 조회")
    fun `member find by name`() {
        // given
        val member = Member("koon", 30)
        memberRepository.save(member)

        // when
        val findMember = memberRepository.findByName(member.name)
            .orElseThrow { IllegalStateException("Member not found.") }

        // then
        assertEquals(findMember.id, member.id)
        assertEquals(findMember.name, member.name)
    }
}

우선 given, when, then에 맞춰서 진행해볼게요. 먼저 given에서는 회원을 저장합니다. 그리고 when에서 저장된 값을 조회하기 위해서 이름을 조회하는 findByName() 함수를 실행합니다. Optional을 return 하는 함수이므로 orElseThrow를 사용하여 예외를 처리합니다. 따라서 저장이 되지 않았다면 IllegalStateException이 나타나게 됩니다.


테스트 코드의 장점. 전체 테스트

이렇게 작성한 모든 테스트는 전체 테스트를 한번에 실행이 가능합니다. 실행시켜 보도록 할게요.

위에서 만든 테스트 코드 전체를 실행하면 다음과 같이 테스트 결과를 보여줍니다. 만약 테스트가 실패가 난다면 초록색 체크가 아닌 붉은색 오류 코드가 나타납니다.


지금까지 스프링부트 프로젝트를 만들고 Repository 테스트 코드를 만들어서 확인해 보았습니다. 기본적으로 JpaRepository를 상속받아서 사용한 함수들은 안정적이지만 내가 직접 만든 함수들은 안정을 보장할 수 없기 때문에 반드시 테스트 코드를 만들어서 테스트를 해보는 습관이 중요한 것 같습니다.

 

다음 포스팅에서는 Service 코드를 테스트 하는 방법에 대해서 알아보겠습니다. 도움이 되셨으면 합니다. 이상입니다.

댓글