2016-06-06 11 views
1

In Kotlin ,, könnten wir Funktionsobjekt haben und als Funktionsparameter übergeben.Kotlin Unit Test für Funktionsparameter und Objekt

  1. Wie wird ein Komponententest zum Testen der Funktionsobjektlogik erstellt? (z. B. funcParam unten)
  2. Wie Unit-Test die Funktion, die Funktionsparameter hat? (z.B. functionWithFuncParam unten) - d. h. kann ich einen Mock für funcParam erzeugen?

    class MyClass1(val myObject: MyObject) { 
        val funcParam = fun (num: Int): Int { 
         return num * num 
        } 
    
        fun myFunctionOne() { 
         myObject.functionWithFuncParam(funcParam) 
        } 
    } 
    
    class MyObject() { 
        fun functionWithFuncParam(funcParam: (Int) -> Int) { 
         println(funcParam(32)) 
        } 
    } 
    

Antwort

3

Unter der Annahme, funcParam ist public absichtlich Sie es wie jede andere Methode testen:

class MyClass1Tests { 
    val sut = MyClass1(MyObject()) 

    @Test 
    fun `funcParam multiplies input`() { 
     assertThat(sut.funcParam(4), equalTo(16)) 
     assertThat(sut.funcParam(1), equalTo(1)) 
     assertThat(sut.funcParam(0), equalTo(0)) 
     assertThat(sut.funcParam(-10), equalTo(100)) 
    } 
} 

Wenn funcParam privat ist nicht ihr Verhalten direkt testen sollten, sondern nur durch öffentliche Schnittstelle ist es Klasse enthält.

Wenn functionWithFuncParam Testen Sie leicht eine Stub-Implementierung von (Int) -> Int liefern können:

class MyObjectTests { 
    val outContent = ByteArrayOutputStream().apply { 
     System.setOut(PrintStream(this)) 
    } 
    val sut = MyObject() 
    @Test 
    fun `functionWithFuncParam prints function output `() { 
     sut.functionWithFuncParam { 12345678 } 
     assertThat(outContent.toString(), containsString("12345678")) 
    } 
} 

Wenn Sie MyClass1 Interaktion mit MyObject eine Möglichkeit testen möchten ist Schnittstelle MyObject von in MyClass1 umgesetzt zu verwenden. Normalerweise ist die beste Wahl, wenn zwei Klassen unterscheiden sich Mitarbeiter in einem Sinne, dass sie getrennt meist nicht verwandten Verhalten haben:

interface FunctionalObj { 
    fun functionWithFuncParam(funcParam: (Int) -> Int) 
} 
class MyClass1(val myObject: FunctionalObj) { 
//omitted for brevity 
} 
class MyClass1Tests { 
    var params = mutableListOf<(Int)->Int>() 
    val sut = MyClass1(object: FunctionalObj { 
     override fun functionWithFuncParam(funcParam: (Int) -> Int) { params.add(funcParam) } 
    }) 

    @Test 
    fun `myFunctionOne calls delegate`() { 
     sut.myFunctionOne() 
     assertThat(params.size, equalTo(1)) 
     assertThat(params[0], equalTo(sut.funcParam))//only if `funcParam` is public 
    } 
} 

Wenn MyClass1 und MyObject Wechselwirkung komplexer ist (dh beinhaltet mehr Anrufe sowohl queries and commands) es würde bedeuten, dass sie Kollegen arbeiten eng zusammen. In diesem Fall kann die Verwendung von Mocks zu spröden und schwer zu schreibenden Tests führen.

+0

Danke miensol. Ich denke darüber nach, ob ich meinObject verspotze und das 'myFunctionOne' testen möchte, um zu verifizieren, dass es' functionWithFuncParam' aufruft. Gibt es eine Möglichkeit, "any()" für das Funktionsparam zu liefern? – Elye

+0

@Elye sehe mein Update. Was an "myObject" übergeben wird, erscheint mir wie ein Implementierungsdetail - und es ist im Allgemeinen eine schlechte Idee, sich in Tests auf sie zu verlassen. Man testet ihr Verhalten nicht gemeinsam und verlässt sich nicht auf Mocks? – miensol