Je travaille sur un pot de Kotlin où je tente de se moquer d'une entrée à une fonctionMockito Mocks Behaving Comme Spies: Kotlin
class MyService
fun serviceFunction(input: ClassFromAnotherLibrary): Output {
val foo = input.memberFunction()
Il se trouve que memberFunction
a été ajouté à cette catégorie dans mon paquet via une fonction d'extension au niveau du package
fun ClassFromAnotherLibrary.memberFunction() : Foo {
val mapper = jacksonObjectMapper()
return mapper.readValue(this.serializedFoo, Foo::class.java)
}
maintenant, je veux écrire un test pour le serviceFunction
, mais je veux railler sur l'appel memberFunction
(je tests séparés pour cela).
Donc, dans mon test Mockito JUnit, je fais ce qui suit
val service = Service()
val mockClassFromAnotherLibrary = mock<ClassFromAnotherLibrary>()
val mockFoo = mock<Foo>()
whenever(mockClassFromAnotherLibrary.memberFunction())
.thenReturn(mockFoo)
service.serviceFunction(mockClassFromAnotherLibrary)
j'attendre à ce que la mise en œuvre effective de de memberFunction
serait jamais appelé, et que ma maquette intercepteraient toute tentative de l'appeler et au lieu retour mon mockFoo
.
Ce qui est en fait passe est la configuration whenever
pour se moquer de la méthode est appeler la fonction sous-jacente, provoquant une NullPointerException
lorsque les mapper
essaie de lire serializedFoo
(ce qui est évidemment nulle).
Ma question est: pourquoi diable est le vrai memberFunction
en cours d'exécution ?? Je suis nouveau sur Mockito et Kotlin, mais j'ai utilisé Jasmine (pour JS) et Spock (pour Groovy/Java) dans le passé, et en se moquant d'un objet dans ces deux frameworks jamais exécuter jamais mocked- hors fonction (que je suis au courant).
Je suis en mesure de travailler sur des questions similaires à cela dans le passé en faisant le ClassFromAnotherLibrary
que je suis en train de se moquer avoir un interface
que je me moque au lieu, mais que
- Paraît aki et
- est pas une option dans ce cas (ce n'est pas ma classe à modifier, il vient d'une autre bibliothèque)
pour référence, ce sont les gradle pertinentes dépendances mon projet utilise:
compile "com.fasterxml.jackson.module:jackson-module-kotlin:2.8.9"
compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.8.9"
compile "com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.8.9"
testCompile 'junit:junit:4.12'
testCompile "org.jetbrains.kotlin:kotlin-test:1.1.4-3"
testCompile "org.jetbrains.kotlin:kotlin-test-junit:1.1.4-3"
testCompile "com.nhaarman:mockito-kotlin:1.3.0"
testCompile "org.mockito:mockito-inline:2.8.47"
J'ai également mis en place un fichier MockMaker
dans mon dossier test/resources
pour permettre mock-maker-inline
, bien que je ne comprends pas tout à fait ce qu'il est que peut accomplir (vu une pointe à ce sujet here)
Merci à tout Kotlin/Mockito
Vous dites qu'une fonction d'extension Kotlin (qui a accès à 'this') est implémentée comme une fonction statique de classe sous le capot? Est-ce que cela veut dire que c'est aussi un argument implicite (ceci)? Je ne savais pas que Mockito ne pouvait pas se moquer des méthodes statiques, bon à savoir! –
Oui. Exactement comme ça. –
Merci d'avoir signalé cela!Pour tous ceux qui ne veulent pas prendre la parole de Rafal (j'aime toujours avoir plusieurs sources), voici un post expliquant: https://android.jlelse.eu/the-ugly-truth-about- extension-fonctions-en-kotlin-486ec49824f4 –