lorsque j'exécute un test mockito se produit WrongTypeOfReturnValue Exception

94

Détail de l'erreur:

org.mockito.exceptions.misusing.WrongTypeOfReturnValue: 
Boolean cannot be returned by updateItemAttributesByJuId()
updateItemAttributesByJuId() should return ResultRich
This exception might occur in wrongly written multi-threaded tests.
Please refer to Mockito FAQ on limitations of concurrency testing.

mon code:

@InjectMocks
protected ItemArrangeManager arrangeManagerSpy = spy(new ItemArrangeManagerImpl());
@Mock
protected JuItemWriteService juItemWriteService;

when(arrangeManagerSpy
    .updateItemAttributes(mapCaptor.capture(), eq(juId), eq(itemTO.getSellerId())))
    .thenReturn(false);

Comme vous pouvez le voir, j'appelle whensur updateItemAttributes(ce qui renvoie a boolean) pas sur updateItemAttributesByJuId.

  1. Pourquoi Mockito tente-t-il de renvoyer un booleande updateItemAttributesByJuId?
  2. Comment cela peut-il être rectifié?
Windbell confus
la source

Réponses:

190

Selon https://groups.google.com/forum/?fromgroups#!topic/mockito/9WUvkhZUy90 , vous devez reformuler votre

when(bar.getFoo()).thenReturn(fooBar)

à

doReturn(fooBar).when(bar).getFoo()
gna
la source
3
C'est un bon conseil. J'avais également ce problème lors du test d'une @Repositoryméthode Spring DAO avec @Aspect . si je le fais when(someDao.someMethod()).thenReturn(List<xxx>), j'ai cette exception WrongTypeOfReturnValue. Grâce au débogage, je peux voir que la someMethodméthode est en fait appelée dans l'instruction ci-dessus et déclenche le conseil Around et renvoie un nullmais Mockito attend un List<xxx>.
LeOn - Han Li
Ça a marché pour moi. Obrigado!
Saxophoniste
Excellente réponse. C'est sauvé ma journée.
user3198259 le
40

Une autre raison pour un message d'erreur similaire est d'essayer de se moquer d'une finalméthode. Il ne faut pas essayer de se moquer des méthodes finales (voir Moquages ​​de la méthode finale ).

J'ai également confronté l'erreur dans un test multi-thread. Réponse de gna a fonctionné dans ce cas.

Arvidaa
la source
19

Problème très intéressant. Dans mon cas, ce problème a été causé lorsque j'ai essayé de déboguer mes tests sur cette ligne similaire:

Boolean fooBar;
when(bar.getFoo()).thenReturn(fooBar);

La remarque importante est que les tests s'exécutaient correctement sans débogage.

De toute façon, lorsque j'ai remplacé le code ci-dessus par l'extrait de code ci-dessous, j'ai pu déboguer la ligne de problème sans problème.

doReturn(fooBar).when(bar).getFoo();
Luke
la source
Merci, il semble qu'il y ait le même problème avec les classes de données Kotlin que les champs, et votre solution l'a résolu!
Mohsen Mirhoseini
6

Pour moi, cela signifiait que je dirigeais ceci:

a = Mockito.mock(SomeClass.class);
b = new RealClass();
when(b.method1(a)).thenReturn(c); 
// within this method1, it calls param1.method2() -- note, b is not a spy or mock

Donc, ce qui se passait, c'est que mockito détectait qui a.method2()était appelé, et me disait que je ne pouvais pas revenir cde a.method2()ce qui était faux.

Correction: utilisez la doReturn(c).when(b).method1(a)syntaxe de style (au lieu de when(b.method1(a)).thenReturn(c);), qui vous aidera à découvrir le bogue caché de manière plus concise et plus rapide.

Ou dans ce cas particulier, après avoir fait cela, il a commencé à afficher le "NotAMockException" plus précis, et je l'ai changé pour ne plus essayer de définir une valeur de retour à partir d'un objet non simulé.

rogerdpack
la source
1
Même erreur que moi aussi. Je me suis moqué de la méthode utilisée dans method1, exécuté et j'ai obtenu cette exception. Il a été résolu une fois que j'ai supprimé ce code.
Praveen.883
5

J'ai récemment eu ce problème. Le problème était que la méthode que j'essayais de simuler n'avait pas de modificateur d'accès. L'ajout de public a résolu le problème.

not_john
la source
5

J'ai eu cette erreur car dans mon test j'avais deux attentes, une sur une maquette et une sur le type de béton

MyClass cls = new MyClass();
MyClass cls2 = Mockito.mock(Myclass.class);
when(foo.bar(cls)).thenReturn(); // cls is not actually a mock
when(foo.baz(cls2)).thenReturn();

Je l'ai corrigé en changeant les cls pour être également un simulacre

Tzafrir
la source
4

Dans mon cas, le problème a été causé en essayant de se moquer d'une méthode statique et en oubliant d'appeler mockStaticla classe. J'ai également oublié d'inclure la classe dans le@PrepareForTest()

ACV
la source
2

Si vous utilisez des annotations, vous devrez peut-être utiliser @Mock au lieu de @InjectMocks. Parce que @InjectMocks fonctionne ensemble comme @Spy et @Mock. Et @Spy garde une trace des méthodes récemment exécutées et vous pouvez avoir l'impression que des données incorrectes sont renvoyées / sous-titrées.

aneth pattnaik
la source
2
" @InjectMocksfonctionne comme @Spyet @Mockensemble." <- cela me semble faux. D'où avez-vous entendu cela?
Etienne Miret
2

Dans mon cas, j'utilisais à la fois @RunWith(MockitoJUnitRunner.class)et MockitoAnnotations.initMocks(this). Quand j'ai enlevé MockitoAnnotations.initMocks(this)cela a fonctionné correctement.

ihebiheb
la source
2

Dans mon cas, le bean a été initialisé en utilisant l' annotation @Autowired au lieu de @MockBean

Donc, de cette façon, la moquerie des DAO et des services lève une telle exception

S.Dayneko
la source
1
Oui, dans mon cas, un test de service d'application Spring-Boot, MockBean doit être utilisé lors de la simulation d'un Bean. Merci!
Isaac Philip
1

Erreur:

org.mockito.exceptions.misusing.WrongTypeOfReturnValue: La
chaîne ne peut pas être retournée par size ()
size () devrait retourner int
***
Si vous ne savez pas pourquoi vous obtenez l'erreur ci-dessus, lisez la suite.
En raison de la nature de la syntaxe ci-dessus, un problème peut survenir car:
1. Cette exception peut se produire dans des
tests multithreads mal écrits .
Veuillez vous référer à la FAQ Mockito sur les limites des tests de concurrence.
2. Un espion est stubblé en utilisant la syntaxe when (spy.foo ()). Then (). Il est plus sûr de
stub espions -
- avec la famille de méthodes doReturn | Throw (). Plus d'informations dans javadocs pour la
méthode Mockito.spy ().

Code réel:

@RunWith(PowerMockRunner.class)
@PrepareForTest({ Object.class, ByteString.class})

@Mock
private ByteString mockByteString;

String testData = dsfgdshf”;
PowerMockito.when(mockByteString.toStringUtf8()).thenReturn(testData); 
// throws above given exception

Solution pour résoudre ce problème:

1er Supprimer l'annotation «@Mock».

private ByteString mockByteString;

2e ajout PowerMockito.mock

mockByteString = PowerMockito.mock(ByteString.class);
MUNISAMIE DE DHANDAYUTHAPANI
la source
1

J'ai récemment rencontré ce problème en se moquant d'une fonction dans une classe de données Kotlin . Pour une raison inconnue, l'un de mes tests s'est terminé dans un état figé. Lorsque j'ai réexécuté les tests, certains de mes tests qui avaient déjà réussi ont commencé à échouer avec l' WrongTypeOfReturnValueexception.

Je me suis assuré que j'utilisais org.mockito:mockito-inlinepour éviter les problèmes avec les classes finales (mentionnés par Arvidaa), mais le problème est resté. Ce qui a résolu le problème pour moi, c'est d' arrêter le processus et de redémarrer Android Studio . Cela a mis fin à mon test gelé et les tests suivants ont réussi sans problème.

Simonevertsson
la source
1

@MockBean manquant sur le haricot dont vous voulez vous moquer

Bouddha
la source
1

J'ai eu ce problème WrongTypeOfReturnValueparce que je me suis moqué d'une méthode renvoyant un java.util.Optional;avec un com.google.common.base.Optional;dû à mon formateur ajoutant automatiquement les importations manquantes.

Mockito me disait juste que "méthode quelque chose () devrait retourner facultatif" ...

RotS
la source
1

Pour moi, le problème était les tests multithreads qui faisaient du stubbing / vérification sur une maquette partagée. Cela a conduit à lancer une WrongTypeOfReturnValueexception au hasard .

Ce test n'est pas correctement rédigé avec Mockito. Les mocks ne doivent pas être accessibles à partir de plusieurs threads.

La solution était de faire des simulations locales à chaque test.

Damian
la source
1

TL; DR Si certains arguments de votre test le sont null, veillez à simuler l'appel de paramètre avec isNull()au lieu de anyXXX().


J'ai eu cette erreur lors de la mise à niveau de Spring Boot 1.5.x vers 2.1.x. Spring boot est livré avec son propre Mockito, qui est maintenant également mis à niveau vers 2.x (voir par exemple Dépendances de Spring boot 2.1.2 )

Mockito a changé le comportement de la anyXXX()méthode, où XXXest String, Longetc. Voici les Javadoc anyLong():

Depuis Mockito 2.1.0, autoriser uniquement les valeurs Long, nulln'est donc plus une valeur valide. Comme les wrappers primitifs peuvent être Nullables, l'API suggérée pour faire correspondre le null wrapper serait #isNull(). Nous avons estimé que ce changement rendrait les tests de harnais beaucoup plus sûrs qu'avec Mockito 1.x.

Je vous suggère de déboguer au point où votre maquette est sur le point d'être appelée et d'inspecter, si au moins un argument l'est null. Dans ce cas, assurez-vous que vous préparez votre maquette avec isNull()au lieu de par exemple anyLong().

Donc ça:

when(MockedClass.method(anyString());

devient:

when(MockedClass.method(isNull());
Younes EO
la source
-1

C'est mon cas:

//given
ObjectA a = new ObjectA();
ObjectB b = mock(ObjectB.class);
when(b.call()).thenReturn(a);

Target target = spy(new Target());
doReturn(b).when(target).method1();

//when
String result = target.method2();

Ensuite, j'obtiens cette erreur:

org.mockito.exceptions.misusing.WrongTypeOfReturnValue: 
ObjectB$$EnhancerByMockitoWithCGLIB$$2eaf7d1d cannot be returned by method2()
method2() should return String

Peux-tu deviner?

Le problème est que Target.method1 () est une méthode statique. Mockito me prévient complètement d'une autre chose.

Surasin Tancharoen
la source