Comment puis-je me moquer d'une expression lambda qui est passée comme paramètre dans un appel de méthode void?
J'ai la structure de classe suivante que je dois tester, mais je ne peux même pas l'instancier à cause de son constructeur.
Existe-t-il un moyen de se moquer de l'appel de méthode someManager.doSomething ?
Ou un moyen de se moquer de item.isDoItemSave?
Je ne peux pas le comprendre et SomeClass.setDoSave jette un pointeur nul sur l'appel de retour ( SomeClass line 18 ), puisque doSave est nul.
Classe que je souhaite instancier:
class SomeClassTest {
private SomeClass someClass;
@Mock
private SomeManager someManagerMock;
@BeforeEach
void setUp() {
MockitoAnnotations.initMocks(this);
this.someClass = new SomeClass(someManagerMock);
}
@Test
void someClassTest() {
someClass.anyOtherMethod();
}
}
SomeManager.doSomething is void:
@FunctionalInterface
public interface ItemUpdate {
void update(Item item);
}
ItemUpdate est une interface fonctionnelle:
public void doSomething(ItemUpdate update){
Item item = new Item();
update.update(item);
}
Je ne peux pas refactoriser ce constructeur, qui sait ce qui va se passer, le code est extrêmement couplé.
Je veux juste pouvoir instancier SomeClass .
Ma classe de test ressemble à ceci, naturellement les tests échouent dans @BeforeEach sur SomeClass appel du constructeur:
public SomeClass() {
private Boolean doSave;
private SomeManager someManager;
private SaveAction action;
public SomeClass(SomeManager someManager) {
this.someManager = someManager;
action = setDoSave() ? SAVE : null;
}
private boolean setDoSave() {
if(doSave == null) {
someManager.doSomething(item -> {
doSave = item.isDoItemSave();
});
}
return doSave;
}
}
3 Réponses :
Je ne peux pas le comprendre et SomeClass.setDoSave lance un pointeur nul, puisque doSave est nul.
SomeClass.setDoSave renvoie NPE car la variable d'instance someManager est null .
Essayez d'ajouter @RunWith (MockitoJUnitRunner.class) à votre classe de test.
Ce n'est pas vrai, premièrement, cette annotation n'est pas requise avec la façon dont mon test est structuré. 2ème Je sais exactement d'où vient le npe et je dois me moquer de doSave = item.isDoItemSave (); pour renvoyer une valeur booléenne. Je ne sais tout simplement pas comment faire ça.
Pour l'instant, j'ai apporté des modifications pour que SomeClass s'instancie au moins. Leçon apprise, surveillez vos affectations de booléen à booléen.
private boolean setDoSave() {
if(doSave == null) {
someManager.doSomething(item -> {
doSave = item.isDoItemSave();
});
}
return doSave != null ? doSave : false;
}
Je laisse cette question ouverte en espérant que quelqu'un avec une meilleure connaissance des frameworks de moquerie puisse fournir un moyen de se moquer de ce cas.
Un rapide coup d'œil à la documentation montre l'exemple suivant que j'ai appliqué à votre situation
@BeforeEach
void setUp() {
MockitoAnnotations.initMocks(this);
//configure the mock
// Java 8 - style 2 - assuming static import of AdditionalAnswers
doAnswer(answerVoid(ItemUpdate update) -> {
Item item = new Item();
//...populate item as needed
update.update(item);
})
.when(someManagerMock).doSomething(any(ItemUpdate.class));
this.someClass = new SomeClass(someManagerMock);
}
Référence Prise en charge des réponses personnalisées Java 8
Notez que je n'ai pas testé cela. Je vais sur la base de ce qui a été montré dans la documentation.
C'est génial, merci beaucoup. J'ai lu votre commentaire précédent et mis en œuvre exactement cela, juste avant de voir votre réponse. Merci encore. Je suppose que je dois entraîner mon google foo si je ne trouve pas ce document par moi-même. :)
pouvez-vous spécifier plus de détails comme, le cas de test existant que vous avez écrit et le numéro de ligne où NullPointerException se produit
@AmitPatil s'il vous plaît lire ma question, je ne peux même pas instancier cette classe. Il n'y a pas de cas de test. J'ai ajouté ma classe de test et clarifié où le pointeur nul est lancé.
@curiosa J'ai ajouté le code de ma classe de test. J'ai du mal à comprendre comment me moquer de cette méthode vide, qui renvoie automatiquement une valeur via lambda.
Qu'est-ce que
Itemet que faititem.isDoItemSave ()?@MaxVollmer Item n'est qu'un pojo.
item.isDoItemSave (), comme la convention de dénomination l'implique, renvoie la valeur booléenne du champ doItemSave à l'intérieur de Item.@curiosa Je sais, je l'ai fait mais ça ne va toujours pas exécuter
doSave = item.isDoItemSave ();qui à son tour aboutira au même npe.@MaxVollmer C'est du code réel, je devais juste renommer les choses. La question est, étant donné cette structure d'appel de méthode, quelle est une manière possible de se moquer d'elle?
@IgorFlakiewicz recherche
doAnswer-whenavec des membres mockito et moqueurs de void