J'ai un dernier cours, quelque chose comme ça:
public final class RainOnTrees{
public void startRain(){
// some code here
}
}
J'utilise cette classe dans une autre classe comme celle-ci:
public class Seasons{
RainOnTrees rain = new RainOnTrees();
public void findSeasonAndRain(){
rain.startRain();
}
}
et dans ma classe de test JUnit car Seasons.java
je veux me moquer de la RainOnTrees
classe. Comment puis-je faire cela avec Mockito?
Réponses:
La simulation des classes / méthodes finales / statiques est possible uniquement avec Mockito v2.
ajoutez ceci dans votre fichier gradle:
Ce n'est pas possible avec Mockito v1, à partir de la FAQ Mockito :
la source
Mockito 2 prend désormais en charge les classes et méthodes finales !
Mais pour l'instant, c'est une fonction "d'incubation". L'activation nécessite certaines étapes décrites dans Quoi de neuf dans Mockito 2 :
la source
org.mockito.plugins.MockMaker
fichier dans le bon dossier.Vous ne pouvez pas vous moquer d'une classe finale avec Mockito, car vous ne pouvez pas le faire vous-même.
Ce que je fais, c'est de créer une classe non finale pour envelopper la classe finale et l'utiliser comme délégué. Un exemple de ceci est la
TwitterFactory
classe, et voici ma classe moquable:L'inconvénient est qu'il y a beaucoup de code passe-partout; l'avantage est que vous pouvez ajouter certaines méthodes qui peuvent se rapporter à votre activité d'application (comme getInstance qui prend un utilisateur au lieu d'un accessToken, dans le cas ci-dessus).
Dans votre cas, je créerais une
RainOnTrees
classe non finale qui déléguerait à la classe finale. Ou, si vous pouvez le rendre non final, ce serait mieux.la source
@Delegate
pour gérer une grande partie du passe-partout.ajoutez ceci dans votre fichier gradle:
ceci est une configuration pour faire fonctionner mockito avec les classes finales
la source
org.mockito.exceptions.base.MockitoInitializationException: Could not initialize inline Byte Buddy mock maker. (This mock maker is not supported on Android.)
Utilisez Powermock. Ce lien montre comment le faire: https://github.com/jayway/powermock/wiki/MockFinal
la source
Powermock
pour me moquer des classes finales et des méthodes statiques pour augmenter ma couverture qui a été officiellement vérifiéeSonarqube
. La couverture était de 0% depuis SonarQube, pour quelque raison que ce soit, elle ne reconnaît pas les classes qui utilisent Powermock n'importe où à l'intérieur. J'ai pris moi et mon équipe un certain temps pour le réaliser à partir d'un fil en ligne. Ce n'est donc qu'une des raisons de faire attention à Powermock et de ne pas l'utiliser.Juste pour faire un suivi. Veuillez ajouter cette ligne à votre fichier de notes:
J'ai essayé différentes versions de mockito-core et mockito-all. Aucun d'eux ne fonctionne.
la source
Je suppose que vous l'avez fait
final
parce que vous voulez empêcher les autres classes de s'étendreRainOnTrees
. Comme le suggère Effective Java (point 15), il existe une autre façon de garder une classe proche pour l'extension sans la fairefinal
:Supprimez le
final
mot - clé;Faites son constructeur
private
. Aucune classe ne pourra l'étendre car elle ne pourra pas appeler lesuper
constructeur;Créez une méthode d'usine statique pour instancier votre classe.
En utilisant cette stratégie, vous pourrez utiliser Mockito et garder votre classe fermée pour l'extension avec peu de code standard.
la source
J'ai eu le même problème. Étant donné que la classe que j'essayais de simuler était une classe simple, j'en ai simplement créé une instance et je l'ai renvoyée.
la source
Essayez ceci:
Ça a marché pour moi. "SomeMockableType.class" est la classe parente de ce que vous voulez simuler ou espionner, et someInstanceThatIsNotMockableOrSpyable est la classe réelle que vous souhaitez simuler ou espionner.
Pour plus de détails jetez un œil ici
la source
Une autre solution de contournement, qui peut s'appliquer dans certains cas, consiste à créer une interface implémentée par cette classe finale, à modifier le code pour utiliser l'interface au lieu de la classe concrète, puis à se moquer de l'interface. Cela vous permet de séparer le contrat (interface) de l'implémentation (classe finale). Bien sûr, si vous voulez vraiment vous lier à la classe finale, cela ne s'appliquera pas.
la source
En fait, il y a un moyen que j'utilise pour espionner. Cela ne fonctionnerait pour vous que si deux conditions préalables sont remplies:
Veuillez rappeler l'article 16 de Java efficace . Vous pouvez créer un wrapper (non final) et transférer tous les appels à l'instance de la classe finale:
Maintenant, vous pouvez non seulement vous moquer de votre classe finale, mais aussi l'espionner:
la source
Dans Mockito 3 et plus, j'ai le même problème et je l'ai résolu à partir de ce lien
Mock classes et méthodes finales avec Mockito comme suit
la source
Gain de temps pour les personnes confrontées au même problème (Mockito + Final Class) sur Android + Kotlin. Comme dans Kotlin, les classes sont finales par défaut. J'ai trouvé une solution dans l'un des exemples Google Android avec le composant Architecture. Solution choisie ici: https://github.com/googlesamples/android-architecture-components/blob/master/GithubBrowserSample
Créez les annotations suivantes:
Modifiez votre fichier gradle. Prenons l'exemple d'ici: https://github.com/googlesamples/android-architecture-components/blob/master/GithubBrowserSample/app/build.gradle
Vous pouvez maintenant annoter n'importe quelle classe pour la rendre ouverte aux tests:
la source
Cela peut être fait si vous utilisez Mockito2, avec la nouvelle fonction d'incubation qui prend en charge la simulation des classes et méthodes finales.
Points clés à noter:
1. Créez un fichier simple avec le nom «org.mockito.plugins.MockMaker» et placez-le dans un dossier nommé «mockito-extensions». Ce dossier doit être disponible sur le chemin de 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 le mécanisme d'extension mockito et utiliser cette fonction d'opt-in.
Les exemples de classes sont les suivants: -
FinalClass.java
}
Foo.java
}
FooTest.java
}
J'espère que ça aide.
Article complet présent ici mocking-the-unmockable .
la source
Oui même problème ici, on ne peut pas se moquer d'un dernier cours avec Mockito. Pour être précis, Mockito ne peut pas se moquer / espionner ce qui suit:
Mais utiliser une classe wrapper me semble un gros prix à payer, alors achetez plutôt PowerMockito.
la source
Je pense que vous devez réfléchir davantage en principe. Au lieu de cela, la classe finale utilise plutôt son interface et son interface factice.
Pour ça:
ajouter
et vous moquer de votre interface:
la source
Veuillez regarder JMockit . Il a une documentation complète avec beaucoup d'exemples. Voici un exemple de solution à votre problème (pour simplifier, j'ai ajouté un constructeur
Seasons
pour injecter uneRainOnTrees
instance simulée ):la source
Les solutions fournies conjointement par RC et Luigi R. Viggiano sont peut-être la meilleure idée.
Bien que Mockito ne puisse pas , par conception, se moquer des classes finales, l'approche de délégation est possible . Cela a ses avantages:
Dans votre scénario de test, vous transférez délibérément les appels vers le système testé. Par conséquent, par la conception, votre décoration ne pas faire quoi que ce soit.
Par conséquent, votre test peut également démontrer que l'utilisateur peut uniquement décorer l'API au lieu de l'étendre.
Sur une note plus subjective: je préfère garder les frameworks au minimum, c'est pourquoi JUnit et Mockito me suffisent généralement. En fait, restreindre cette voie m'oblige parfois à refactoriser pour de bon aussi.
la source
Si vous essayez d'exécuter le test unitaire sous le test dossier de , la meilleure solution est très bien. Suivez-le en ajoutant une extension.
Mais si vous voulez l'exécuter avec une classe liée à Android comme le contexte ou l'activité qui se trouve dans le dossier androidtest , la réponse est pour vous.
la source
Ajoutez ces dépendances pour exécuter mockito avec succès:
testImplementation 'org.mockito: mockito-core: 2.24.5'
testImplementation "org.mockito: mockito-inline: 2.24.5"
la source
Comme d'autres l'ont dit, cela ne fonctionnera pas avec Mockito. Je suggère d'utiliser la réflexion pour définir les champs spécifiques de l'objet utilisé par le code testé. Si vous vous retrouvez souvent à faire cela, vous pouvez envelopper cette fonctionnalité dans une bibliothèque.
Soit dit en passant, si vous êtes le seul à marquer les classes finales, arrêtez de le faire. J'ai rencontré cette question parce que je travaille avec une API où tout a été marqué comme final pour éviter mon besoin légitime d'extension (moqueuse), et je souhaite que le développeur n'ait pas supposé que je n'aurais jamais besoin d'étendre la classe.
la source
final
devrait être la valeur par défaut.Pour nous, c'est parce que nous avons exclu le mockito-inline du koin-test. Un module gradle en avait réellement besoin et, pour des raisons, n'a échoué que sur les versions (les versions de débogage dans l'EDI ont fonctionné) :-P
la source
Pour la classe finale, ajoutez ci-dessous pour simuler et appeler statique ou non statique.
1- ajoutez ceci au niveau de la classe @SuppressStatucInitializationFor (valeur = {nom de classe avec package})
2- PowerMockito.mockStatic (classname.class) se moquera de la classe
3- puis utilisez votre instruction when pour renvoyer l'objet simulé lors de l'appel de la méthode de cette classe.
Prendre plaisir
la source
N'a pas essayé la finale, mais pour le privé, en utilisant la réflexion, supprimez le modificateur travaillé! ont vérifié plus loin, cela ne fonctionne pas pour la finale.
la source