Comment simuler une classe finale avec mockito
J'ai une classe final, quelque chose comme ceci:
public final class RainOnTrees{
public void startRain(){
//some code here
}
}
Je suis à l'aide de cette classe dans la classe comme ceci:
public class Seasons{
RainOnTrees rain = new RainOnTrees();
public void findSeasonAndRain(){
rain.startRain();
}
}
et dans ma classe de test JUnit pour Seasons.java
je veux de se moquer de l' RainOnTrees
classe. Comment puis-je faire cela avec Mockito?
- Mockito ne le permet pas, cependant PowerMock n'.
- Comme de Mockito 2.x, Mockito prend désormais en charge les moqueries de finale de classes et de méthodes.
- Double Possible de se Moquer de la classe finale avec Mockito 2
Vous devez vous connecter pour publier un commentaire.
Se moquant de finale de la statique/classes/méthodes est possible avec Mockito v2 uniquement.
ajouter ceci dans votre gradle fichier:
Ce n'est pas possible avec Mockito v1, de la Mockito FAQ:
Mockito 2 prend désormais en charge final les classes et les méthodes de!
Mais pour l'instant c'est un "incubation" caractéristique. Il nécessite quelques étapes à suivre pour l'activer, qui sont décrits dans Ce qui est Nouveau dans Mockito 2:
org.mockito.plugins.MockMaker
fichier dans le bon dossier.org.mockito:mockito-core
au lieuorg.mockito:mockito-android
pour corriger l'erreur @rcde0.txt
extension.mock-maker-inline
est une SEULE LIGNE danssrc/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
.Vous ne pouvez pas se moquer d'une classe finale avec Mockito, que vous ne pouvez pas le faire par vous-même.
Ce que je fais, est de créer une classe finale pour envelopper la finale de la classe et de l'utiliser en tant que délégué. Un exemple de ceci est
TwitterFactory
classe, et c'est mon mockable classe:L'inconvénient, c'est qu'il y a beaucoup de code réutilisable; l'avantage est que vous pouvez ajouter quelques méthodes qui peuvent se rapporter à votre application d'entreprise (comme la getInstance qui est prise d'un utilisateur au lieu d'une accessToken, dans le cas ci-dessus).
Dans votre cas, je voudrais créer un non définitif
RainOnTrees
classe que délégué de la classe finale. Ou, si vous pouvez le faire non définitive, elle serait mieux.@Delegate
à gérer beaucoup de le passe-partout.ajouter ceci dans votre gradle fichier:
c'est une configuration pour faire de mockito travailler avec final classes
org.mockito.exceptions.base.MockitoInitializationException: Could not initialize inline Byte Buddy mock maker. (This mock maker is not supported on Android.)
Utilisation Powermock. Ce lien montre, comment le faire: https://github.com/jayway/powermock/wiki/MockFinal
Juste de faire un suivi. Merci d'ajouter cette ligne à votre gradle fichier:
J'ai essayé différentes versions de mockito-core et mockito-tous. Ni de leur travail.
Je suppose que vous l'avez fait
final
parce que vous voulez empêcher les autres classes de l'extension deRainOnTrees
. Comme Efficace Java suggère (article 15), il y a une autre façon de garder une classe à proximité de l'extension sans en fairefinal
:Supprimer la
final
de mots-clés;Faire son constructeur
private
. Aucune classe ne sera en mesure de le prolonger, car il ne sera pas en mesure d'appeler lesuper
constructeur;Créer une statique de la méthode de factorisation pour instancier ta classe.
Par l'utilisation de cette stratégie, vous serez en mesure d'utiliser Mockito et de garder votre classe fermée pour l'extension avec un peu de code réutilisable.
J'ai eu le même problème. Depuis la classe I a été d'essayer de se moquer, c'était une simple classe, j'ai tout simplement créé une instance de celle-ci et renvoyé que.
Donner à ceci un essai:
Il a travaillé pour moi. "SomeMockableType.class" la classe parent de ce que vous voulez de se moquer ou d'espionnage, et someInstanceThatIsNotMockableOrSpyable est la classe réelle que vous voulez pour se moquer ou espion.
Pour plus de détails, veuillez consulter ici
Une autre solution, qui peut s'appliquer dans certains cas, est de créer une interface implémentée par la classe finale, modifier le code pour utiliser l'interface plutôt que sur le béton de la classe et puis se moquer de l'interface. Cela vous permet de séparer le contrat (interface) à partir de la mise en œuvre (classe finale). Bien sûr, si vous voulez vraiment de se lier à la classe finale, cela ne s'applique pas.
En fait, il ya une façon dont je me sers pour l'espionnage. Il serait travailler pour vous, que si deux conditions sont remplies:
Rappelons l'Article 16 de Efficace Java. Vous pouvez créer un wrapper (non définitif) et de transférer tous les appels à l'instance de la classe finale:
Maintenant, non seulement pouvez-vous vous moquer de votre classe finale, mais aussi espionner:
Cela peut être fait si vous utilisez Mockito2, avec la nouvelle incubation de fonction, qui prend en charge se moquant de finale classes & méthodes.
Points clés à noter:
1. Créer un simple fichier avec le nom “org.mockito.les plugins.MockMaker” et le placer dans un dossier nommé “mockito-extensions”. Ce dossier doit être mis à disposition sur le chemin de la classe.
2. Le contenu du fichier créé ci-dessus doit être une seule ligne comme indiqué ci-dessous:
mock-maker-inline
Les deux étapes ci-dessus sont nécessaires pour activer la mockito mécanisme d'extension et de l'utilisation de cette fonctionnalité d'opt-in.
Exemples de classes sont comme suit:-
FinalClass.java
}
Foo.java
}
FooTest.java
}
Espère que cela aide.
Article complet ici présents se moquant de-la-unmockable.
Gain de temps pour les gens qui sont confrontés à la même question (Mockito + Classe Finale) sur Android + Kotlin. Comme dans Kotlin classes sont finales par défaut. J'ai trouvé une solution dans un de Google Android échantillons avec l'Architecture du composant. Solution choisi à partir d'ici : https://github.com/googlesamples/android-architecture-components/blob/master/GithubBrowserSample
Créer des annotations suivantes :
Modifier votre gradle fichier. Prenez par exemple à partir d'ici : https://github.com/googlesamples/android-architecture-components/blob/master/GithubBrowserSample/app/build.gradle
Maintenant, vous pouvez annoter toute la classe pour faire ouvrir pour les essais de :
Oui même problème ici, on ne peut plus se moquer d'une classe finale avec Mockito. Pour être précis, Mockito ne peut plus se moquer/spy suivantes:
Mais à l'aide d'une classe wrapper me semble un gros prix à payer afin d'obtenir PowerMockito à la place.
Veuillez jeter un oeil à JMockit. Il possède une vaste documentation, avec beaucoup d'exemples. Ici vous avez un exemple de solution de votre problème (pour simplifier, j'ai ajouté constructeur de
Seasons
à injecter moquéRainOnTrees
exemple):Solutions fournies par RC et Luigi R. Viggiano ensemble est peut-être la meilleure idée.
Bien que Mockito ne peut pas, de par sa conception, maquette finale classes, la délégation approche est possible. Cela a ses avantages:
Dans votre cas de test, vous avez délibérément transférer les appels vers le système sous test. Donc, de par sa conception, votre décoration ne pas faire quoi que ce soit.
Donc vous test permet également de démontrer que l'utilisateur peut seulement décorer l'API au lieu de l'étendre.
Sur un plan plus subjectif note:
Je préfère garder les cadres à un minimum, ce qui est pourquoi JUnit et Mockito sont généralement suffisant pour moi. En effet, la restriction de cette façon, parfois, m'oblige à refactoriser pour de bon en tant que bien.
Si vous essayez d'exécuter des tests unitaires en vertu de la test dossier, la solution est très bien. Suivez simplement en ajoutant une extension.
Mais si vous voulez l'exécuter avec liés android classe comme contexte ou de l'activité qui est sous androidtest dossier, la réponse est fait pour vous.
Je pense que vous avez besoin de réfléchir plus en principe. Au lieu de cela vous classe finale d'utilisation de son interface et de la maquette de l'interface à la place.
Pour cela:
ajouter
et se moquer de vous d'interface:
Comme d'autres l'ont dit, cela ne peut pas fonctionner hors de la boîte avec Mockito. Je suggère l'utilisation de la réflexion pour définir les champs spécifiques sur l'objet qui est utilisé par le code en cours de test. Si vous vous retrouver à faire beaucoup, vous pouvez envelopper cette fonction dans une bibliothèque.
En aparté, si vous êtes l'un marquage des classes de finale, arrêter de faire ça. J'ai couru à travers cette question, parce que je suis en train de travailler avec une API où tout a été marquée final pour empêcher mon besoin légitime d'extension (moqueur), et je souhaite que le développeur n'avait pas supposé que je n'aurait pas besoin d'étendre la classe.
final
doit être la valeur par défaut.Pour nous, c'est parce que nous avons exclu mockito en ligne de koin-test. Un gradle module réellement besoin de cette et pour des raisons seulement échoué sur les versions release (debug dans l'IDE de travail) 😛
N'essayez pas définitif, mais pour le privé, l'utilisation de la réflexion supprimer le modificateur travaillé ! avoir vérifié encore, il ne fonctionne pas pour la finale.