Java 当我运行mockito测试时,会发生错误类型的返回值异常
错误详细信息:Java 当我运行mockito测试时,会发生错误类型的返回值异常,java,mockito,Java,Mockito,错误详细信息: 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. Plea
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);
如您所见,我在updateItemAttribute
上调用而不是updateItemAttribute ByJUID
上调用(它返回一个boolean
)
为什么Mockito试图从updateItemAttribute ByJUID
返回布尔值李>
如何纠正这一点
根据,你应该重新表述你的观点
when(bar.getFoo()).thenReturn(fooBar)
到
出现类似错误消息的另一个原因是试图模拟final
方法。人们不应该试图模仿final方法(参见)
我还遇到了多线程测试中的错误。gna的回答在这种情况下有效。如果您使用注释,可能需要使用@Mock而不是@InjectMocks。因为@InjectMocks同时充当@Spy和@Mock。@Spy会跟踪最近执行的方法,您可能会觉得返回了不正确的数据。我最近遇到了这个问题。问题是我试图模拟的方法没有访问修饰符。添加public解决了这个问题。在我的例子中,问题是由于试图模拟静态方法而忘记调用类上的mockStatic
。另外,我忘了将该类包含到@PrepareForTest()
中,因为在我的测试中,我有两个期望,一个是模拟的,一个是具体类型的
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更改为模拟来修复它错误:
org.mockito.exceptions.misusing.ErrorTypeOfReturnValue:
无法通过size()返回字符串
size()应返回int
***
如果您不确定为什么会出现上述错误,请继续阅读。
由于语法的性质,上述问题可能会出现,因为:
1.此异常可能发生在写入错误的多线程系统中
测试。
有关并发测试的限制,请参阅Mockito常见问题解答。
2.间谍使用when(spy.foo()).then()语法进行存根。使用
存根间谍-
-使用doReturn | Throw()方法族。更多关于
javadocs的信息
spy()方法
实际代码:
@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
解决此问题的解决方案:
第一次删除注释“@Mock”
private ByteString mockByteString;
第二个添加PowerMockito.mock
mockByteString = PowerMockito.mock(ByteString.class);
对我来说,这意味着我在运行:
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()
,并告诉我无法从a.method2()返回c
,这是错误的
修复:使用doReturn(c).when(b).method1(a)
样式语法(而不是when(b.method1(a)).thenReturn(c);
),这将帮助您更简洁、快速地发现隐藏的bug
或者在这个特殊的例子中,在这样做之后,它开始显示更准确的“NotAMockException”,我将其更改为不再尝试从非mock对象设置返回值。非常感兴趣的问题。
在我的例子中,这个问题是在我尝试调试类似线路上的测试时引起的:
Boolean fooBar;
when(bar.getFoo()).thenReturn(fooBar);
值得注意的是,测试在没有调试的情况下正确运行
无论如何,当我用下面的代码片段替换上面的代码时,我就能够毫无问题地调试问题行了
doReturn(fooBar).when(bar).getFoo();
我最近在模拟Kotlin数据类中的函数时遇到了这个问题。不知什么原因,我的一次测试运行最终处于冻结状态。当我再次运行测试时,以前通过的一些测试开始失败,出现ErrorTypeOfReturnValue
异常
我确保使用org.mockito:mockitoinline
来避免最终类的问题(Arvidaa提到过),但问题仍然存在。对我来说,解决这个问题的办法是终止进程并重新启动Android Studio。这终止了我冻结的测试运行,并且以下测试运行顺利通过。这是我的情况:
//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完全警告我另一件事。在你想要模拟的bean上缺少@MockBean在我的例子中,我同时使用了@RunWith(MockitoJUnitRunner.class)
和MockitoAnnotations.initMocks(this)
。当我删除MockitoAnnotations.initMocks(this)
时,它工作正常。我遇到了这个问题错误类型的返回值
,因为我模拟了一个返回java.util.Optional的方法代码>带有com.google.common.base.Optional代码>由于我的格式化程序自动添加缺少的导入
Mockito只是告诉我“methodsomething()应该返回可选的”…在我的例子中,bean是使用@Autowired annotation而不是@MockBean初始化的
因此,以这种方式模拟DAO和服务会引发这样的异常对我来说,问题是在共享模拟上执行存根/验证的多线程测试。它导致随机抛出错误类型的返回值
异常
这不是使用Mockito正确编写的测试。
不应从多个线程访问模拟
解决方案是在每个测试中进行局部模拟。TL;DR如果测试中的某些参数为null
,请确保使用isNull()
而不是anyXXX()
模拟参数调用
从Spring boot 1.5.x升级到2.1.x时,我遇到了这个错误。Spring boot附带了自己的Mockito,现在也升级到了2.x(参见示例)
Mockito已经更改了anyXXX()
方法的行为,其中XXX
是String
,Long
,等等。下面是anyLong()
的javadoc:
自Mockito 2.1.0以来,只允许有值的Long
,因此
null
不再是原始包装器的有效值
如果可为空,则建议的API将匹配
null
b
org.mockito.exceptions.misusing.WrongTypeOfReturnValue:
ObjectB$$EnhancerByMockitoWithCGLIB$$2eaf7d1d cannot be returned by method2()
method2() should return String
when(MockedClass.method(anyString());
when(MockedClass.method(isNull());