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
Item
et 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-when
avec des membres mockito et moqueurs de void