quando eu executo o teste mockito, ocorre a exceção WrongTypeOfReturnValue

94

Detalhe do erro:

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.

meu código:

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

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

Como você pode ver, eu estou chamando whenon updateItemAttributes(que faz retorno a boolean) não no updateItemAttributesByJuId.

  1. Por que Mockito está tentando retornar um booleande updateItemAttributesByJuId?
  2. Como isso pode ser corrigido?
Windbell confuso
fonte

Respostas:

190

De acordo com https://groups.google.com/forum/?fromgroups#!topic/mockito/9WUvkhZUy90 , você deve reformular sua

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

para

doReturn(fooBar).when(bar).getFoo()
gna
fonte
3
Essa é uma ótima dica. Eu também estava tendo esse problema ao testar alguns @Repositorymétodos Spring DAO com @Aspect . se eu fizer when(someDao.someMethod()).thenReturn(List<xxx>)isso, recebo essa exceção WrongTypeOfReturnValue. Através da depuração, posso ver que o someMethodmétodo foi realmente chamado na instrução acima e aciona o Around Advice e retorna um, nullmas Mockito está esperando um List<xxx>.
LeOn - Han Li
Funcionou para mim. Obrigado!
Saxofonista
Excelente resposta. Salvou meu dia.
user3198259
40

Outro motivo para mensagem de erro semelhante é tentar simular um finalmétodo. Não se deve tentar simular métodos finais (consulte Simulação do método final ).

Também confrontei o erro em um teste multithread. A resposta por gna funcionou nesse caso.

Arvidaa
fonte
19

Problema muito interessado. No meu caso, esse problema foi causado quando tentei depurar meus testes nesta linha semelhante:

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

A observação importante é que os testes foram executados corretamente sem depuração.

De qualquer forma, quando substituí o código acima pelo trecho de código abaixo, fui capaz de depurar a linha do problema sem problemas.

doReturn(fooBar).when(bar).getFoo();
Lucas
fonte
Obrigado, parece que há o mesmo problema com classes de dados Kotlin como campos, e sua solução resolveu!
Mohsen Mirhoseini de
6

Para mim, isso significava que eu estava executando este:

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

Então, o que estava acontecendo é que Mockito foi detectar que a.method2()estava sendo chamado, e me dizendo que eu não poderia voltar ca partir de a.method2()que é errado.

Correção: use a doReturn(c).when(b).method1(a)sintaxe de estilo (em vez de when(b.method1(a)).thenReturn(c);), que o ajudará a descobrir o bug oculto de forma mais concisa e rápida.

Ou, neste caso específico, depois de fazer isso, ele começou a mostrar a "NotAMockException" mais precisa e eu mudei para não mais tentar definir um valor de retorno de um objeto não simulado.

rogerdpack
fonte
1
O mesmo erro que eu também cometi. Eu simulei o método usado em method1, executei e peguei essa exceção. Foi resolvido assim que removi esse código.
Praveen.883
5

Recentemente tive esse problema. O problema era que o método que eu estava tentando simular não tinha modificador de acesso. Adicionar público resolveu o problema.

not_john
fonte
5

Eu tive esse erro porque em meu teste eu tinha duas expectativas, uma em uma simulação e outra em concreto

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();

Consertei alterando cls para ser uma simulação também

Tzafrir
fonte
4

No meu caso, o problema foi causado por tentar simular um método estático e esquecer de chamar mockStatica classe. Também esqueci de incluir a classe no@PrepareForTest()

ACV
fonte
2

Se você estiver usando anotações, pode ser necessário usar @Mock em vez de @InjectMocks. Porque @InjectMocks funciona como @Spy e @Mock juntos. E @Spy mantém registro de métodos executados recentemente e você pode sentir que dados incorretos são retornados / substituídos.

dillip pattnaik
fonte
2
" @InjectMocksfunciona como @Spye @Mockjunto." <- isso parece errado para mim. De onde você ouviu isso?
Etienne Miret
2

No meu caso, estava usando ambos @RunWith(MockitoJUnitRunner.class)e MockitoAnnotations.initMocks(this). Quando removi MockitoAnnotations.initMocks(this), funcionou corretamente.

ihebiheb
fonte
2

No meu caso, o bean foi inicializado usando a anotação @Autowired em vez de @MockBean

Portanto, desta forma, zombar de DAOs e serviços lança tal exceção

S.Dayneko
fonte
1
Sim, no meu caso, um teste de serviço de aplicativo Spring-Boot, MockBean deve ser usado ao simular um Bean. obrigado!
Isaac Philip
1

Erro:

org.mockito.exceptions.misusing.WrongTypeOfReturnValue:
String não pode ser retornada por size ()
size () deve retornar int
***
Se você não souber por que está obtendo o erro acima, continue lendo.
Devido à natureza da sintaxe acima, o problema pode ocorrer porque:
1. Essa exceção pode ocorrer em
testes multithread escritos incorretamente .
Consulte as Perguntas frequentes do Mockito sobre as limitações dos testes de simultaneidade.
2. Um espião é esboçado usando a sintaxe when (spy.foo ()). Then (). É mais seguro
stub spies -
- com a família de métodos doReturn | Throw (). Mais em javadocs para o
método Mockito.spy ().

Código real:

@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

Solução para corrigir esse problema:

1. Remova a anotação “@Mock”.

private ByteString mockByteString;

2º Adicionar PowerMockito.mock

mockByteString = PowerMockito.mock(ByteString.class);
DHANDAYUTHAPANI MUNISAMY
fonte
1

Recentemente, encontrei esse problema ao simular uma função em uma classe de dados Kotlin . Por alguma razão desconhecida, uma das minhas execuções de teste acabou em um estado congelado. Quando eu executei os testes novamente, alguns dos meus testes que haviam passado anteriormente começaram a falhar com a WrongTypeOfReturnValueexceção.

Garanti que estava usando org.mockito:mockito-inlinepara evitar os problemas com as aulas finais (mencionadas pela Arvidaa), mas o problema permaneceu. O que resolveu para mim foi interromper o processo e reiniciar o Android Studio . Isso encerrou minha execução de teste congelada e as execuções de teste a seguir foram aprovadas sem problemas.

simonevertsson
fonte
1

Falta @MockBean no bean que você deseja simular

Buda
fonte
1

Eu tenho esse problema WrongTypeOfReturnValueporque simulei um método que retorna um java.util.Optional;com um com.google.common.base.Optional;devido ao meu formatador adicionar automaticamente as importações ausentes.

Mockito estava me dizendo que "método something () deve retornar opcional" ...

RotS
fonte
1

Para mim, o problema eram os testes multithread que faziam stub / verificação em simulações compartilhadas. Isso levou a uma WrongTypeOfReturnValueexceção aleatória .

Este não é um teste escrito corretamente usando Mockito. Mocks não devem ser acessados ​​de vários threads.

A solução foi fazer simulações locais para cada teste.

Damian
fonte
1

TL; DR Se alguns argumentos em seu teste forem null, certifique-se de simular a chamada de parâmetro com em isNull()vez de anyXXX().


Recebi este erro ao atualizar do Spring boot 1.5.x para 2.1.x. O Spring boot vem com seu próprio Mockito, que agora também é atualizado para 2.x (consulte, por exemplo, Dependências do Spring boot 2.1.2 )

Mockito mudou o comportamento para o anyXXX()método, onde XXXé String, Longetc. Aqui está o javadoc de anyLong():

Desde o Mockito 2.1.0, permite apenas valor Long, portanto nullnão é mais um valor válido Como os wrappers primitivos são anuláveis, a API sugerida para corresponder ao nullwrapper seria #isNull(). Sentimos que essa mudança tornaria o equipamento de testes muito mais seguro do que era com o Mockito 1.x.

Eu sugiro que você depure até o ponto em que sua simulação está prestes a ser chamada e inspecione se pelo menos um argumento é null. Nesse caso, certifique-se de preparar sua simulação com, em isNull()vez de, por exemplo anyLong().

Então, é isso:

when(MockedClass.method(anyString());

torna-se:

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

Este é o meu caso:

//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();

Então recebo este erro:

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

Você consegue adivinhar?

O problema é que Target.method1 () é um método estático. Mockito me avisa completamente para outra coisa.

Surasin Tancharoen
fonte