J'ai écrit quelques tests unitaires pour une méthode statique. La méthode statique ne prend qu'un seul argument. Le type de l'argument est une classe finale. En termes de code:
public class Utility {
public static Optional<String> getName(Customer customer) {
// method's body.
}
}
public final class Customer {
// class definition
}
Donc , pour la Utility
classe que j'ai créé une classe de test UtilityTests
dans lequel j'ai des tests écrits pour cette méthode, getName
. Le framework de tests unitaires est TestNG et la bibliothèque de simulation utilisée est Mockito
. Un test typique a donc la structure suivante:
public class UtilityTests {
@Test
public void getNameTest() {
// Arrange
Customer customerMock = Mockito.mock(Customer.class);
Mockito.when(...).thenReturn(...);
// Act
Optional<String> name = Utility.getName(customerMock);
// Assert
Assert.assertTrue(...);
}
}
Quel est le problème ?
Alors que les tests s'exécutent avec succès localement, à l'intérieur d'IntelliJ, ils échouent sur Jenkins (lorsque je pousse mon code dans la branche distante, une génération est déclenchée et des tests unitaires s'exécutent à la fin). Le message d'erreur est comme suit:
org.mockito.exceptions.base.MockitoException: ne peut pas se moquer / espionner classe com.packagename.Customer Mockito ne peut pas se moquer / espionner parce que: - classe finale
Qu'est-ce que j'ai essayé?
J'ai cherché un peu, pour trouver une solution mais je n'y suis pas arrivée. Je note ici que je ne suis pas autorisé à changer le fait qu'il Customer
s'agit d'une classe finale . En plus de cela, j'aimerais si possible ne pas changer du tout sa conception (par exemple, créer une interface, qui contiendrait les méthodes que je veux simuler et déclarer que la classe Customer implémente cette interface, comme Jose l'a correctement souligné dans son commentaire). La chose que j'ai essayée est la deuxième option mentionnée au mockito-final . Malgré le fait que cela ait résolu le problème, cela freine certains autres tests unitaires :(, qui ne peuvent pas être résolus de manière apparente.
Des questions
Voici donc les deux questions que j'ai:
- Comment est-ce possible en premier lieu? Le test ne devrait-il pas échouer localement et à Jenkins?
- Comment cela peut-il être corrigé en fonction des contraintes que j'ai mentionnées ci-dessus?
Merci d'avance pour votre aide.
la source
enable final
configuration fonctionne dans votre espace de travail, mais lorsqu'elle est exécutée surJenkins
son impossible de trouver ce fichier. Vérifiez oùJenkins
le fichier est recherché et s'il est réellement présent ou non.Customer
a- t -il une logique ou s'agit-il simplement d'une classe de données stupide? Si c'est juste un tas de champs avec des getters et des setters, alors vous pouvez simplement l'instancier.Réponses:
Une autre approche consisterait à utiliser le modèle «méthode pour classer».
Voici un bon blog sur le sujet: https://simpleprogrammer.com/back-to-basics-mock-élimination-patterns/
la source
C'est évidemment une sorte de spécificités env. La seule question est - comment déterminer la cause de la différence.
Je vous suggère de vérifier la
org.mockito.internal.util.MockUtil#typeMockabilityOf
méthode et de comparer ce quimockMaker
est réellement utilisé dans les deux environnements et pourquoi.Si
mockMaker
c'est la même chose - comparer les classes chargéesIDE-Client
vsJenkins-Client
- ont-ils une différence sur le moment de l'exécution du test.Le code suivant est écrit en supposant OpenJDK 12 et Mockito 2.28.2, mais je pense que vous pouvez l'ajuster à n'importe quelle version réellement utilisée.
Avec une règle distincte pour les simulateurs en ligne:
la source
Assurez-vous d'exécuter le test avec les mêmes arguments. Vérifiez si vos configurations d'exécution intellij correspondent aux jenkins. https://www.jetbrains.com/help/idea/creating-and-editing-run-debug-configurations.html . Vous pouvez essayer d'exécuter le test sur la machine locale avec les mêmes arguments que sur jenkins (depuis le terminal), si cela échoue, cela signifie que le problème est dans les arguments
la source
org.mockito.plugins.MockMaker
existe également dans la machine jenkins. J'utilise la même JVM dans les machines bot. Je vais vérifier les 3 que vous avez indiqués. Merci