2016-04-10 27 views
10

Come probabilmente sappiamo, per impostazione predefinita, la classe Kotlin, una volta definita, è definitiva, a meno che non sia dichiarata esplicitamente open.È possibile utilizzare Mockito con Kotlin senza aprire la classe?

Questo pubblicherebbe una sfida quando vogliamo deriderlo usando Mockito. Dobbiamo dichiararlo esplicitamente come open. C'è un modo per evitare di dichiararlo come open mentre è in grado di deriderlo per i nostri test?

+1

Si potrebbe fare implementare un'interfaccia e simulare quello invece. – AndroidEx

+0

Grazie a @AndroidEx. Se potessi elaborare e fornire un esempio funzionante di questo, sarebbe davvero d'aiuto. Grazie! – Elye

+1

Dai uno sguardo a https://github.com/nhaarman/mockito-kotlin – marcospereira

risposta

6

Mockito2 ora può anche prendere in giro le classi finali.

Tuttavia, questa funzione è opt-in, quindi è necessario attivarla manualmente.
Per farlo, è necessario definire un file che contiene la linea /mockito-extensions/org.mockito.plugins.MockMakermock-maker-inline

Vedi esempio
http://hadihariri.com/2016/10/04/Mocking-Kotlin-With-Mockito/ o https://github.com/mockito/mockito/wiki/What%27s-new-in-Mockito-2#unmockable
per una rapida introduzione

su un lato nota, questo attualmente doesn't work for android

+0

Funziona con Dexmaker? Per i test di strumentazione Android? –

+0

@folkyatina nessuna idea, scusa – Lovis

+2

Purtroppo no, non sembra funzionare. –

8

Ci sono tre modi Sono consapevole di quanto si può prendere in giro le classi Kotlin:

  1. utilizzare le interfacce, invece di classi. In questo caso, sostituisci tutti gli usi di una particolare classe con l'interfaccia corrispondente. E nel testare il codice si prende in giro l'interfaccia.

    interface Something { /* ... */ } 
    
    class SomethingImpl : Something { /* ... */ } 
    
    fun processSomething(something: Something) { /* ... */ } 
    
    val something = mock(Something::class.java) 
    processSomething(mock) 
    
  2. Attivare le classi, che non è molto conveniente.

  3. Utilizzare PowerMock anziché Mockito. Usando il suo ClassLoader puoi fare molto di più che con Mockito.

Preferisco il primo approccio perché è una buona idea lavorare con interfacce invece di classi anche se non si utilizzano i framework di simulazione.

+0

Grazie Michael. Quindi per ogni classe che dobbiamo testare, dobbiamo invece implementare un'interfaccia? Sembra più un cambio di codice che 'apri' la classe, o mi sono perso qualcosa ... – Elye

+0

Certo, ma è un grande passo verso un'architettura migliore :) – Michael

+4

Creazione di un'interfaccia separata senza un motivo valido (da un OO o API punto di vista del design) è eccessivamente inginante in quanto aggiunge solo complessità. È anche peggio che rendere una classe inutilmente "aperta". (E, no, non creare l'interfaccia non * viola * il principio di GoF di "programma su un'interfaccia, non un'implementazione".) –

8

Il plugin MockMaker non sembra funzionare durante l'esecuzione di prove di macchina per caffè espresso. Pertanto, è possibile utilizzare Kotlin all-open pugin.

Aggiungere il plugin in build.gradle:

buildscript { 
    dependencies { 
     classpath "org.jetbrains.kotlin:kotlin-allopen:$kotlin_version" 
    } 
} 

apply plugin: "kotlin-allopen" 

Specificare l'annotazione che renderà la classe libera:

allOpen { 
    annotation("com.my.MyMockable") 
} 

Creare l'annotazione che può essere utilizzato per annotare le classi:

@Target(AnnotationTarget.CLASS) 
annotation class MyMockable 

Quindi, per rendere la classe e i suoi metodi pubblici Mockable (aperto), annotare i t con la tua annotazione:

@MyMockable 
+0

Mi è piaciuta questa soluzione per essere la meno invadente e quella che offre maggior controllo sulle alternative. – Fabio

+0

Funziona completamente su Android. Grazie! –

Problemi correlati