2016-06-22 10 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 "" 
    } 
} 

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) 
    } 
} 

またはケースであなたがcallerFunSomeObjectを模擬したい場合:

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()への呼び出しを模擬する最も簡単な方法(と私がお勧めする方法)は、模擬オブジェクトを滑らせる何らかの方法を提供することです。

object SomeObject { 
    fun someFun() {} 
} 

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

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

ここでのアイデアは、変更したいことを変更することです。上記のようにシングルトンに作用するシングルトンとトップレベル関数を必要としているのであれば、上で示したように、パブリックシグネチャを変更せずにトップレベル関数をテスト可能にする方法は、実装をinternal関数に移すことですモックを滑らせることができます。

2

Kotlinのための非常に素晴らしい新しいモックライブラリがあります。それは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)) 
} 

Kotlin言語の制限にもかかわらず、あなたがいる場合、オブジェクトの新しいインスタンスを作成することができますテストロジックには次のものが必要です。

val newObjectMock = mockk<MockObj>() 
2

クラス代理人を使用して、余分なライブラリを使わずにObjectをモックできます。ここで

は私の提案は、あなたがそれ以外の場合は、それが実際の実装だ使用しますが、動作を変更しますデリゲートオブジェクトを設定することができ、あなたのテストでは

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

関連する問題