roon-replica / toy-blog-BE

토이 프로젝트 / 블로그 기능 / 백엔드만 / 구현,협업,배포 연습
0 stars 0 forks source link

단위 테스트하는 법 학습하고 적용해보기 #55

Open roon-replica opened 1 year ago

roon-replica commented 1 year ago
sunwng commented 1 year ago

제가 진행하고 있는 동아리 프로젝트에서 테스트를 진행하고 있는데, 코틀린이지만 예시를 여기에 올려볼까요?

roon-replica commented 1 year ago

네 도움이 될 것 같습니다!

sunwng commented 1 year ago

먼저, 다른 테이블의 두 PK를 복합키로 설정후 이를 PK로 갖는 테이블에 대한 테스트입니다.

@Import(TestConfig::class)
@DataJpaTest
@AutoConfigureTestDatabase(connection = EmbeddedDatabaseConnection.H2)
@TestPropertySource(properties = ["spring.config.location = classpath:application-test.yml"])
class CafeLikeRepositoryTest(
    @Autowired
    private val cafeLikeRepository: CafeLikeRepository
) : AnnotationSpec() {
    @Test
    fun `좋아요 등록 테스트`() {
        cafeLikeRepository.save(CafeLike(1L, 2L))
        cafeLikeRepository.existsById(UserAndCafe(1L, 2L)) shouldBe true
    }

    @Test
    fun `좋아요 삭제 테스트`() {
        cafeLikeRepository.save(CafeLike(1L, 2L))
        cafeLikeRepository.deleteById(UserAndCafe(1L, 2L))
        cafeLikeRepository.existsById(UserAndCafe(1L, 2L)) shouldBe false
    }

    @Test
    fun `좋아요 없는지 테스트`() {
        cafeLikeRepository.existsById(UserAndCafe(3L, 2L)) shouldBe false
    }

    @Test
    fun `좋아요 리스트 테스트`() {
        cafeLikeRepository.save(CafeLike(1L, 2L))
        cafeLikeRepository.save(CafeLike(1L, 3L))
        val list = cafeLikeRepository.findAllByUserId(1L)
        list.size shouldBe 2
        list[0].cafeId shouldBe 2L
        list[1].cafeId shouldBe 3L
    }
}

H2 인메모리 DB를 사용 했고, TestConfig 는 queryDSL 사용하는 코드가 있어서 여기서는 사용하지 않지만 임포트했습니다. 모든 빈을 띄울 필요가 없기에 DataJpaTest 로 테스트 했습니다.

sunwng commented 1 year ago

이건 서비스에 있는 로직 테스트 입니다.

class CafeServiceTest : AnnotationSpec() {
    private val cafeRepository = mockk<CafeRepository>()
    private val cafeRepositoryImpl = mockk<CafeRepositoryImpl>()
    private val userRepository = mockk<UserRepository>()
    private val cafeLikeRepository = mockk<CafeLikeRepository>()
    private val userService = mockk<UserService>()
    private val cafeService = CafeService(cafeRepository, cafeRepositoryImpl, cafeLikeRepository, userService)

    @BeforeAll
    fun `초기 설정`() {
        val testCafe = Cafe("test", "test", "test", "test", "test")
        every { cafeRepository.findById(any()) } returns Optional.of(testCafe)
    }

    @Test
    fun `WrongCheck 켜지는지 바뀌는지 테스트`() {
        cafeService.markCafeWrong(1L)
        val testCafe = cafeRepository.findById(1L)
        testCafe.get().wrongCheck shouldBe true
    }

    @Test
    fun `WorngCheck 꺼지는지 테스트`() {
        cafeService.markCafeRight(1L)
        val testCafe = cafeRepository.findById(1L)
        testCafe.get().wrongCheck shouldBe false
    }
}

mockk 는 kotlin에서 사용하는 mock 라이브러리인데, java 쪽 mockito와 큰 차이 없다고 알고 있습니다. mock 으로 repository를 만들고 이의 행동을 정의 한 후 테스트 했습니다. 제 생각은, repository가 잘 작동하는지 테스트 (단순 조회라면 굳이 할 필욘 없다고 봐요) 후에, 해당 기능을 mock을 사용하여 정의하면 (이미 검증된 기능이므로 자체적으로 기능을 정의 가능하다고 생각) 서비스를 테스트 할 수 있다고 생각합니다.