2016-06-22 2 views

답변

5

그냥 객체를 모의 라이브러리로 조롱 할 수있는 것보다 인터페이스를 구현하게하십시오. 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) 
    } 
} 
+0

이것은 안티 패턴처럼 보입니다 ... 테스트 목적으로 만 주 코드에서 추가 클래스/인터페이스를 생성해서는 안됩니다! – Kerooker

+0

여분의 클래스가 아니라 단지 인터페이스. 그리고 JVM에서 테스트 할 때 가장 좋은 방법이기 때문에 그렇게해야합니다. – IRus

0

바이트 코드를 조작하지 않으면 코드를 기꺼이 변경할 수 없다면 대답은 '아니오'입니다. SomeObject.someFun()에 대한 callerFun의 호출을 모의하기위한 가장 직접적인 방법 (그리고 내가 권장하는 방법)은 모의 객체를 풀 수있는 방법을 제공하는 것입니다.

예컨대

object SomeObject { 
    fun someFun() {} 
} 

fun callerFun() { 
    _callerFun { SomeObject.someFun() } 
} 

internal inline fun _callerFun(caller:() -> Unit) { 
    caller() 
} 

아이디어는 변경하려는 사항을 변경하는 것입니다. 위에서 설명한 것처럼 싱글 톤과 최상위 함수가 그 싱글 톤에서 작동하는 것을 확신한다면 최상위 함수를 공개 서명을 변경하지 않고 테스트 할 수있게 만드는 방법은 구현을 internal 함수로 옮기는 것입니다 모의를 미끄러 뜨리는 것을 허용합니다.

2

가 코 틀린에 대한 아주 좋은 새 조롱 라이브러리있다 :

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>() 
2

당신은 클래스를 대표를 사용하여, 여분의 라이브러리없이 객체를 조롱 할 수 있습니다.

여기, 그렇지 않으면 그것은 실제 구현의 사용, 내 제안

당신이 행동을 바꿀 위임 객체를 설정할 수 있습니다 테스트에서
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

관련 문제