当我运行模拟测试时,发生WrongTypeOfReturnValue异常


94

错误详情:

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.

我的代码:

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

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

正如你所看到的,我呼吁when有关updateItemAttributes(其中不归路boolean)不是updateItemAttributesByJuId

  1. 为什么尝试的Mockito返回一个booleanupdateItemAttributesByJuId
  2. 如何纠正?

Answers:


190

根据https://groups.google.com/forum/?fromgroups#!topic/mockito/9WUvkhZUy90,您应改写

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

doReturn(fooBar).when(bar).getFoo()

3
这是一个很好的提示。@Repository使用@Aspect测试某些Spring DAO方法时,我也遇到了这个问题。如果我这样做when(someDao.someMethod()).thenReturn(List<xxx>),则会收到此WrongTypeOfReturnValue异常。通过调试,我可以看到该someMethod方法实际上是在上面的语句中调用的,并触发了“周围通知”并返回a,null但Mockito期望a List<xxx>
LeOn-韩立

为我工作。Obrigado!
萨克斯管演奏者

优秀答案。它拯救了我的一天。
user3198259

40

出现类似错误消息的另一个原因是试图模拟final方法。一个人不应该尝试模拟最终方法(请参阅Final方法模拟)。

我还在多线程测试中遇到了错误。gna的回答在这种情况下起作用。


19

非常感兴趣的问题。就我而言,这个问题是在我尝试在以下类似行上调试测试时引起的:

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

重要的注意事项是测试在没有调试的情况下可以正确运行。

无论如何,当我用下面的代码片段替换上面的代码时,我便能够调试问题行而没有问题。

doReturn(fooBar).when(bar).getFoo();

谢谢,看来Kotlin数据类和字段存在相同的问题,您的解决方案解决了它!
Mohsen Mirhoseini,

6

对我来说,这意味着我正在运行:

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

所以发生的是,mockito正在检测到a.method2()被调用的内容,并告诉我我不能ca.method2()错误中返回。

修复:使用doReturn(c).when(b).method1(a)样式语法(而不是when(b.method1(a)).thenReturn(c);),这将帮助您更简洁,更快速地发现隐藏的错误。

或在这种特定情况下,这样做之后,它开始显示更准确的“ NotAMockException”,并且我将其更改为不再尝试从非模拟对象设置返回值。


1
我也犯过同样的错误。我嘲笑了method1中使用的方法,执行并得到了这个异常。一旦删除该代码,它就解决了。
Praveen.883,19年

5

我最近有这个问题。问题是我尝试模拟的方法没有访问修饰符。增加公众解决了这个问题。


5

我有这个错误,因为在测试中我有两个期望,一个是模拟的,一个是具体类型的

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

我也通过将cls更改为模拟来修复它


4

在我的情况下,问题是由于尝试模拟静态方法而忘记调用mockStatic该类而引起的。我也忘了将课程纳入@PrepareForTest()


2

如果您使用注释,则可能需要使用@Mock而不是@InjectMocks。因为@InjectMocks可以和@Spy和@Mock一起使用。@Spy会跟踪最近执行的方法,您可能会感到返回/取消了错误的数据。


2
@InjectMocks工作原理 @Spy@Mock在一起。” <-对我来说似乎是错误的。你是从哪儿来的?
Etienne Miret

2

就我而言,我同时使用@RunWith(MockitoJUnitRunner.class)MockitoAnnotations.initMocks(this)。当我删除MockitoAnnotations.initMocks(this)它正常工作。


2

在我的情况下,已使用@Autowired注释而不是@MockBean初始化了bean

因此,通过这种方式对DAO和服务进行模拟会抛出此类异常


1
是的,在我的案例中是Spring-Boot应用程序服务测试,在模拟Bean时应使用MockBean。谢谢!
艾萨克·菲利普

1

错误:

org.mockito.exceptions.misusing.WrongTypeOfReturnValue:
size()无法返回字符串
size()应该返回int
***
如果您不确定为什么会出现上述错误,请继续阅读。
由于上述语法的性质,可能会出现以下问题:
1 .错误编写的多线程 测试中可能会发生此异常

请参阅Mockito常见问题解答关于并发测试的限制。
2.使用when(spy.foo())。then()语法对间谍进行打桩。 使用doReturn | Throw()系列方法对
间谍进行存根比较安全
。有关
Mockito.spy()方法的更多Javadocs。

实际代码:

@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

解决此问题的解决方案:

1删除注释“ @Mock”。

private ByteString mockByteString;

第二添加 PowerMockito.mock

mockByteString = PowerMockito.mock(ByteString.class);

1

我最近在模拟Kotlin数据类中的函数时遇到了此问题。由于某种未知的原因,我的测试运行最终陷入了冻结状态。当我再次运行测试时,以前通过的某些测试因WrongTypeOfReturnValue异常而开始失败。

我确保我正在使用org.mockito:mockito-inline以避免最终类的问题(由Arvidaa提及),但是问题仍然存在。对我而言,解决该问题的方法终止进程并重新启动Android Studio。这终止了我的冻结测试运行,并且以下测试运行顺利通过。


1

您要模拟的bean上缺少@MockBean


1

我遇到了这个问题,WrongTypeOfReturnValue因为我格式化了一个java.util.Optional;带有a 的方法,com.google.common.base.Optional;原因是我的格式化程序会自动添加缺少的导入内容。

Mockito只是在说我“ method something()应该返回Optional”。


1

对我来说,问题在于对共享模拟进行存根/验证的多线程测试。它导致随机抛出WrongTypeOfReturnValue异常。

这不是使用Mockito正确编写的测试。不应从多个线程访问模拟。

解决的办法是使模拟对于每个测试都是本地的。


1

TL; DR如果测试中有某些参数,请null确保使用isNull()代替来模拟参数调用anyXXX()


从Spring Boot 1.5.x升级到2.1.x时出现此错误。Spring Boot带有自己的Mockito,现在也已升级到2.x(请参阅例如Spring Boot 2.1.2的依赖项

已经的Mockito改变行为的anyXXX()方法,其中XXXStringLong等这里的javadoc的anyLong()

由于Mockito 2.1.0仅允许valued Long,因此 null不再是有效值。由于原始包装器可以为空,因此建议 null包装器匹配的 API为#isNull()。我们认为,这一更改将使测试利用起来比Mockito 1.x更安全。

我建议您调试到将要调用您的模拟并检查是否至少有一个参数是null。在这种情况下,请确保您使用isNull()而不是例如准备模拟anyLong()

所以这:

when(MockedClass.method(anyString());

变成:

when(MockedClass.method(isNull());

-1

这是我的情况:

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

然后我得到这个错误:

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

猜一下?

问题在于Target.method1()是静态方法。Mockito完全警告我另一件事。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.