티스토리 뷰

배경

validator를 따로 분리하는 작성을 수행하였습니다.

이 때, 예외가 없다면 리턴값이 없는 메서드로 구성했었습니다.

이 validator 클래스를 사용하는 service Test 내에서는 해당 validator를 mocking해서 테스트하려고 했습니다.

package com.laboratorykkoon9.kotlinspring.cafe.service

import com.laboratorykkoon9.kotlinspring.cafe.repository.CafeRepository
import org.springframework.stereotype.Service

@Service
class CafeValidator(
    private val cafeRepository: CafeRepository,
) {
    fun createValidator(name: String) {
        if(cafeRepository.existsByName(name)) {
            throw IllegalArgumentException("${name}은(는) 이미 존재하는 이름입니다.")
        }
    }
}

테스트를 하려고 하는 Servcie 코드는 다음과 같습니다.

suspend fun createCafe(
    cafeDto: CreateCafeDto
) = cafeDto.toEntity()
    .also {
        cafeValidator.createValidator(it.name)
    }
    .also { cafeRepository.save(it) }
    .also { logger.info("생성된 카페의 이름은 ${it.name}입니다.") }

예외를 발생시키는 mock 방법

먼저 예외를 발생하는 mocking 코드부터 살펴봅시다.

@DataJpaTest
@Import(QuerydslConfig::class)
@AutoConfigureTestDatabase(
    replace = AutoConfigureTestDatabase.Replace.NONE,
)
internal class CafeServiceTest(
    @Autowired private val cafeRepository: CafeRepository,
    @Autowired private val dataSource: DataSource,
): DescribeSpec({
    beforeSpec {
        try {
            dataSource.connection.use {conn ->
                ScriptUtils.executeSqlScript(
                    conn,
                    ClassPathResource("/sql/cafe.sql")
                )
            }
        } catch (e: SQLException) {
            throw RuntimeException(e)
        }
    }

    val cafeValidator = mockk<CafeValidator>()
    val cafeService = CafeService(
        cafeRepository = cafeRepository,
        cafeValidator = cafeValidator
    )

    describe("getCafeInfo") {
        context("모든 카페를 조회하면") {
            val cafe = cafeService.getCafeInfo(Pageable.ofSize(1))
            it("개수는 1개가 나온다.") {
                cafe.content.size shouldBe 1
            }
        }
    }

    describe("createCafe") {
        context("이미 존재하는 카페 이름으로 생성을 시도하면") {
            val cafeDto = CreateCafeDto(
                name = "둥겸의 커피집"
            )
            every { cafeValidator.createValidator(any()) } throws IllegalArgumentException()

            it("예외를 던진다.") {
                shouldThrow<IllegalArgumentException> {
                    cafeService.createCafe(cafeDto)
                }
            }
        }
    }
  }
every { cafeValidator.createValidator(any()) } throws IllegalArgumentException()

위 코드처럼 원하는 예외를 throws 시켜주면 됩니다.

예외를 피하는 mock 방법

다음은 예외없이 지나가는 코드를 살펴봅시다.

context("존재하지 않은 카페 이름으로 생성을 시도하면") {
    val cafeDto = CreateCafeDto(
        name = "둥겸의 커피집1"
    )
    every { cafeValidator.createValidator(any()) } just runs

    it("카페 정보가 잘 저장된다.") {
        val cafe = cafeService.createCafe(cafeDto)
        cafe.name shouldBe "둥겸의 커피집1"
    }
}

위 코드처럼 just runs 처리를 해주면 됩니다.

결론

예외를 발생시키는 mock과 예외를 발생시키지 않은 mock을 살펴봤습니다.

데이터 세팅이 번거롭다면 mock을 활용하는 테스트 작성도 고려해보면 좋을 것 같습니다.

출처

https://mockk.io/

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함