interface `자판기` {
fun `음료수 뽑기`(): String
}
class `콜라 자판기`: `자판기` {
override fun `음료수 뽑기`(): String {
return "콜라"
}
}
class `주스 자판기`: `자판기` {
override fun `음료수 뽑기`(): String {
return "주스"
}
}
abstract class `자판기 이용자` {
// 추상 타입의 필드
abstract val `자판기`: `자판기`
// 메서드 내부에서 추상 타입의 필드를 참조하고 있다
fun `자판기에서 음료수 뽑기`(): String {
return `자판기`.`음료수 뽑기`()
}
}
val `자판기 이용자의 mock` = spyk<`자판기 이용자`>()
context("자판기를 콜라 자판기로 바꾸면") {
// 추상 타입의 필드를 모킹한다
every { `자판기 이용자의 mock`.`자판기` } returns `콜라 자판기`()
test("자판기에서 음료수를 뽑으면 콜라가 나온다") {
`자판기 이용자의 mock`.`자판기`.`음료수 뽑기`() shouldBe "콜라"
// 성공
}
test("자판기에서 음료수를 뽑으면 콜라가 나온다") {
`자판기 이용자의 mock`.`자판기에서 음료수 뽑기`() shouldBe "콜라"
// 성공
}
}
class `자판기 이용자` {
// 구체 타입의 필드
val `자판기`: `자판기` = `주스 자판기`()
// 메서드 내부에서 구체 타입의 필드를 참조하고 있다
fun `자판기에서 음료수 뽑기`(): String {
return `자판기`.`음료수 뽑기`()
}
}
val `자판기 이용자의 mock` = spyk<`자판기 이용자`>()
context("자판기를 콜라 자판기로 바꾸면") {
// 구체 타입의 필드를 모킹한다
every { `자판기 이용자의 mock`.`자판기` } returns `콜라 자판기`()
test("자판기에서 음료수를 뽑으면 콜라가 나온다") {
`자판기 이용자의 mock`.`자판기`.`음료수 뽑기`() shouldBe "콜라"
// 성공
}
test("자판기에서 음료수를 뽑으면 콜라가 나온다") {
`자판기 이용자의 mock`.`자판기에서 음료수 뽑기`() shouldBe "콜라"
// 실패
// 메서드는 "콜라"가 아닌 "주스"를 반환한다
}
}