는 코 틀린 싱글 객체와 그 방법Kotlin 싱글 톤 객체를 조롱하는 방법?
object SomeObject {
fun someFun() {}
}
fun callerFun() {
SomeObject.someFun()
}
이 SomeObject.someFun()
에 전화를 조롱 할 수있는 방법이 있나요의 부르는 재미를 감안할 때?
는 코 틀린 싱글 객체와 그 방법Kotlin 싱글 톤 객체를 조롱하는 방법?
object SomeObject {
fun someFun() {}
}
fun callerFun() {
SomeObject.someFun()
}
이 SomeObject.someFun()
에 전화를 조롱 할 수있는 방법이 있나요의 부르는 재미를 감안할 때?
그냥 객체를 모의 라이브러리로 조롱 할 수있는 것보다 인터페이스를 구현하게하십시오. Junit와 + Mockito + Mockito-Kotlin의 여기 예 :
import com.nhaarman.mockito_kotlin.mock
import com.nhaarman.mockito_kotlin.whenever
import org.junit.Assert.assertEquals
import org.junit.Test
object SomeObject : SomeInterface {
override fun someFun():String {
return ""
}
}
class Caller(val someInterface: SomeInterface) {
fun callerFun():String {
return "Test ${someInterface.someFun()}"
}
}
// Example of use
val test = Caller(SomeObject).callerFun()
interface SomeInterface {
fun someFun():String
}
class SampleTest {
@Test
fun test_with_mock() {
val mock = mock<SomeInterface>()
val caller = Caller(mock)
whenever(mock.someFun()).thenReturn("42")
val answer = caller.callerFun()
assertEquals("Test 42", answer)
}
}
바이트 코드를 조작하지 않으면 코드를 기꺼이 변경할 수 없다면 대답은 '아니오'입니다. SomeObject.someFun()
에 대한 callerFun
의 호출을 모의하기위한 가장 직접적인 방법 (그리고 내가 권장하는 방법)은 모의 객체를 풀 수있는 방법을 제공하는 것입니다.
예컨대
object SomeObject {
fun someFun() {}
}
fun callerFun() {
_callerFun { SomeObject.someFun() }
}
internal inline fun _callerFun(caller:() -> Unit) {
caller()
}
아이디어는 변경하려는 사항을 변경하는 것입니다. 위에서 설명한 것처럼 싱글 톤과 최상위 함수가 그 싱글 톤에서 작동하는 것을 확신한다면 최상위 함수를 공개 서명을 변경하지 않고 테스트 할 수있게 만드는 방법은 구현을 internal
함수로 옮기는 것입니다 모의를 미끄러 뜨리는 것을 허용합니다.
가 코 틀린에 대한 아주 좋은 새 조롱 라이브러리있다 :
import com.nhaarman.mockito_kotlin.mock
import com.nhaarman.mockito_kotlin.whenever
import org.junit.Assert.assertEquals
import org.junit.Test
object SomeObject : SomeInterface {
override fun someFun():String {
return ""
}
}
interface SomeInterface {
fun someFun():String
}
class SampleTest {
@Test
fun test_with_mock() {
val mock = mock<SomeInterface>()
whenever(mock.someFun()).thenReturn("42")
val answer = mock.someFun()
assertEquals("42", answer)
}
}
또는 경우에
당신이 모의SomeObject
callerFun
내부합니다. 그것은
Mockk입니다.
오늘 버전 1.7로 업데이트되어 원하는 방식대로 객체를 모의 할 수 있습니다. 그것의로
는 문서입니다 :
객체는 방법으로 다음과 같은 모의 객체로 변환 할 수 있습니다
:
object MockObj {
fun add(a: Int, b: Int) = a + b
}
objectMockk(MockObj).use {
assertEquals(3, MockObj.add(1, 2))
every { MockObj.add(1, 2) } returns 55
assertEquals(55, MockObj.add(1, 2))
}
코 틀린 언어의 한계에도 불구하고이 객체 경우의 새로운 인스턴스를 생성 할 수 있습니다 테스트 로직은 다음을 필요로합니다 :
val newObjectMock = mockk<MockObj>()
당신은 클래스를 대표를 사용하여, 여분의 라이브러리없이 객체를 조롱 할 수 있습니다.
여기, 그렇지 않으면 그것은 실제 구현의 사용, 내 제안
당신이 행동을 바꿀 위임 객체를 설정할 수 있습니다 테스트에서val someObjectDelegate : SomeInterface? = null
object SomeObject: by someObjectDelegate ?: SomeObjectImpl
object SomeObjectImpl : SomeInterface {
fun someFun() {
println("SomeObjectImpl someFun called")
}
}
interface SomeInterface {
fun someFun()
}
입니다. 위의 과정 이름의
@Beofre
fun setUp() {
someObjectDelegate = object : SomeInterface {
fun someFun() {
println("Mocked function")
}
}
// Will call method from your delegate
SomeObject.someFun()
}
나쁜 있지만, 예를 위해이 목적을 보여줍니다.
SomeObject가 초기화 된 후 대리인이 모든 기능을 처리합니다.
공식에서 더 많이 찾을 수 있습니다 documentation
이것은 안티 패턴처럼 보입니다 ... 테스트 목적으로 만 주 코드에서 추가 클래스/인터페이스를 생성해서는 안됩니다! – Kerooker
여분의 클래스가 아니라 단지 인터페이스. 그리고 JVM에서 테스트 할 때 가장 좋은 방법이기 때문에 그렇게해야합니다. – IRus