【问题标题】:when I run mockito test occurs WrongTypeOfReturnValue Exception当我运行 mockito 测试时发生 WrongTypeOfReturnValue 异常
【发布时间】:2012-06-20 14:26:33
【问题描述】:

错误详情:

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

如您所见,我在updateItemAttributes 上调用when(它确实返回boolean)而不是updateItemAttributesByJuId

  1. 为什么 Mockito 试图从 updateItemAttributesByJuId 返回 boolean
  2. 如何解决这个问题?

【问题讨论】:

    标签: java mockito


    【解决方案1】:

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

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

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

    【讨论】:

    • 这是一个很棒的提示。在使用 @Aspect 测试一些 Spring @Repository DAO 方法时,我也遇到了这个问题。如果我这样做when(someDao.someMethod()).thenReturn(List<xxx>),我得到了这个 WrongTypeOfReturnValue 异常。通过调试,我可以看到 someMethod 方法实际上在上面的语句中被调用并触发了周围建议并返回一个 null 但 Mockito 期待一个 List<xxx>
    • 为我解决了。奥布里加多!
    • 很好的答案。它拯救了我的一天。
    • 如果被mock的方法是static怎么办?
    • @paradocslover 在静态的情况下我认为你必须使用 Powermockt Powermock.mockStatic(foo.class) 然后 PowerMockito.when(Foo.class, "method", ...params).thenReturn (条)
    【解决方案2】:

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

    我在多线程测试中也遇到过这个错误。 gna 的回答在这种情况下有效。

    【讨论】:

      【解决方案3】:

      非常感兴趣的问题。 在我的情况下,当我尝试在类似的行上调试我的测试时导致了这个问题:

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

      重要的一点是测试在没有调试的情况下运行正确。

      无论如何,当我用下面的代码 sn-p 替换上面的代码时,我能够毫无问题地调试问题行。

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

      【讨论】:

      • 谢谢,看来 Kotlin 数据类与字段存在相同的问题,您的解决方案解决了它!
      • 谢谢,我在使用 Kotlin 和 Android 时遇到了同样的问题
      【解决方案4】:

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

      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);),这将帮助您更简洁快速地发现隐藏的错误。

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

      【讨论】:

      • 我也犯了同样的错误。我模拟了method1中使用的方法,执行并得到了这个异常。一旦我删除了该代码,它就得到了解决。
      • 我想我也在做同样的事情:将列表设置为真实对象的字段,然后mock.doSth().getList() mock.doSth() 返回真实对象。
      【解决方案5】:

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

      【讨论】:

        【解决方案6】:

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

        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 也改为模拟来修复它

        【讨论】:

        • 因此可能会出现错误并带有一些提示,但实际情况却大不相同。
        【解决方案7】:

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

        【讨论】:

          【解决方案8】:

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

          【讨论】:

            【解决方案9】:

            如果你使用注解,你可能需要使用@Mock 而不是@InjectMocks。因为@InjectMocks 作为@Spy 和@Mock 一起工作。 @Spy 会跟踪最近执行的方法,您可能会觉得返回/替换了不正确的数据。

            【讨论】:

            • "@InjectMocks 作为@Spy@Mock 一起使用。"
            【解决方案10】:

            TL;DR如果您的测试中的某些参数是null,请务必使用isNull() 而不是anyXXX() 模拟参数调用。


            从 Spring boot 1.5.x 升级到 2.1.x 时出现此错误。 Spring Boot 附带了自己的 Mockito,现在也升级到 2.x(参见例如Dependencies of Spring boot 2.1.2

            Mockito 改变了anyXXX() 方法的行为,其中XXXStringLong 等。这是anyLong() 的javadoc:

            从 Mockito 2.1.0 开始,只允许使用 Long,因此 null 不再是有效值作为原始包装器 可以为空,建议的 API ma​​tch null 包装器将是 #isNull()。我们感受到了这种变化 将使测试工具比使用 Mockito 更安全 1.x.

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

            所以这个:

            when(MockedClass.method(anyString());
            

            变成:

            when(MockedClass.method(isNull());
            

            【讨论】:

              【解决方案11】:

              错误:

              org.mockito.exceptions.misusing.WrongTypeOfReturnValue:
              size() 无法返回字符串
              size() 应该返回 int
              ***
              如果您不确定为什么会出现上述错误,请继续阅读。
              由于上述语法的性质,可能会出现上述问题,因为:
              1. 这个异常可能发生在写错多线程
              测试。
              有关并发测试的限制,请参阅 Mockito 常见问题解答。
              2. 使用 when(spy.foo()).then() 语法对 spy 进行存根。更安全
              存根间谍 -
              - 使用 doReturn|Throw() 系列方法。 javadocs 中的更多内容
              Mockito.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);
              

              【讨论】:

                【解决方案12】:

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

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

                【讨论】:

                  【解决方案13】:

                  在要模拟的 bean 上缺少 @MockBean

                  【讨论】:

                    【解决方案14】:

                    我遇到了这个问题 WrongTypeOfReturnValue,因为我模拟了一个返回 java.util.Optional;com.google.common.base.Optional; 的方法,因为我的格式化程序会自动添加缺少的导入。

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

                    【讨论】:

                      【解决方案15】:

                      在我的例子中,bean 已经使用 @Autowired 注释而不是 @MockBean

                      进行了初始化

                      因此以这种方式模拟 DAO 和服务会引发此类异常

                      【讨论】:

                      • 是的,在我的情况下是 Spring-Boot 应用程序服务测试,在模拟 Bean 时应该使用 MockBean。谢谢!
                      【解决方案16】:

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

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

                      解决方案是让每个测试都本地化模拟。

                      【讨论】:

                        【解决方案17】:

                        就我而言,或者更确切地说是Android 项目的仪器测试,
                        我只需要删除build 目录(强制重建)。

                        也许一个错误的原因太多了!
                        (他们应该已经解决了这个问题)。

                        但我希望这对某人有所帮助
                        d= (◕‿↼ )

                        【讨论】:

                          【解决方案18】:

                          我正在使用 Scala,并且收到这条消息,我错误地在两个 Objects 之间共享了一个 Mock。因此,请确保您的测试彼此独立。并行测试执行显然会产生一些不稳定的情况,因为 Scala 中的对象是单例组合。

                          【讨论】:

                            【解决方案19】:

                            对于我来说,mocked object的类型实际上是一个抽象接口,将类型更改为某个实现类后问题得到解决,

                            改变

                            @Mock
                            private Proxy proxy;
                            

                            @Mock
                            private ProxyImpl proxy;
                            

                            【讨论】:

                              【解决方案20】:

                              这是我的情况:

                              //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 完全警告我另一件事。

                              【讨论】:

                                猜你喜欢
                                • 2014-12-29
                                • 2013-01-07
                                • 2023-03-07
                                • 1970-01-01
                                • 1970-01-01
                                • 2019-01-23
                                • 2017-03-06
                                • 1970-01-01
                                • 1970-01-01
                                相关资源
                                最近更新 更多