【问题标题】:Mockito - Invalid use of argument matchersMockito - 参数匹配器的无效使用
【发布时间】:2013-05-03 17:08:21
【问题描述】:

我有一个正在测试 jms 消息发送的 Junit 测试。我正在使用 Spring jmsTemplate 来执行此操作。在这里,我想在下面的代码中检查 JMS 模板是否调用了发送消息,而不管传递的实际参数的值是什么。

我的发布者方法使用 jmsTemplate 发送方法如下所示..

jmsTemplate.send(jmsQueueProperties.getProperty(key), new MessageCreator()
{
    public Message createMessage(Session session) throws JMSException
    {
        ObjectMessage obj = session.createObjectMessage(dialogueServiceResponse);
        return obj;
}
});

在我的测试中..

JmsTemplate mockTemplate = Mockito.mock(JmsTemplate.class);
...
publisher.publishServiceMessage(response);
....
Mockito.verify(mockTemplate, 
    Mockito.times(1)).send("appointment.queue", 
        Mockito.any(MessageCreator.class));

但是在执行时我得到了

org.mockito.exceptions.misusing.InvalidUseOfMatchersException:参数匹配器的使用无效! ....

原因是由于 Mockito.any(MessageCreator.class) ,但没有办法测试我的发送方法是否正在执行而不在 MessageCreator 中创建实际对象。

更新 有没有办法检查我的 session.createObjectMessage(dialogueServiceResponse) 是否也被调用

【问题讨论】:

  • 模拟和验证不能很好地协同工作。您需要为您希望运行这些验证的类创建一个间谍对象,而不是仅仅模拟它。
  • @3xil3 - 这是错误的。完全可以验证对 Mocked 对象的调用。

标签: unit-testing junit mockito


【解决方案1】:

我认为消息的其余部分会告诉您问题所在。当您为其中一个参数使用参数匹配器时,所有其他参数也必须使用参数匹配器:

Mockito.verify(mockTemplate, Mockito.times(1)).send(
    Mockito.eq("appointment.queue"), 
    Mockito.any(MessageCreator.class));

【讨论】:

  • 谢谢。是的。这有助于解决问题。但是如果我想检查 session.createObjectMessage(dialogueServiceResponse) 是否被调用呢?
  • 您可能必须使用带有模拟会话的真实 JmsTemplate 实例来执行此操作。或者您可以将消息创建外部化到另一个方法,并对这个方法进行单元测试。
【解决方案2】:

我认为你不能在存根之外使用参数匹配器。我也遇到了同样的错误,但是当我返回时,我必须执行新的 string() 而不是 Mockito.anyString() 并且错误消失了。 示例:

Mockito.when(mockedBean.mockedMethod(Mockito.anyString(), 
                                     Mockito.anyInt(),
                                     Mockito.anyInt(),
                                     Mockito.anyInt(),
                                     Mockito.anyBoolean())).thenReturn(new String()); 

【讨论】:

    【解决方案3】:

    我可以看到这个问题是关于 Java 代码的,但我会分享这个问题,因为我们在 Scala 中也使用了 Mockito。

    我从以下模拟 Play.api configurations 的代码中抛出了这个异常

    "Configurations Service" should {
    
        "return all dataset configurations" in {
          val configs = mock[Configuration]
    
          val testData = Seq("SOME VALUE")
    
          val loader = any[ConfigLoader[Seq[String]]]
    
          when(configs.get[Seq[String]](any[String])).thenReturn(testData) // EXCEPTIONN HERE ! 
    
          val configuration: ConfigurationsService = new ConfigurationsService(configs)
    
          assert(configuration.getSupportedDatasets() == testData)
    
        }
      }
    

    在 Scala 中,方法可以有 Implicit parameters configs.get 方法有一个显式参数和一个隐式参数我传递了一个模拟对象,当抛出异常时我想知道发生了什么,因为我没有混合参数和模拟,原来我也必须将模拟传递给隐式参数,这解决了问题。

     val loader = any[ConfigLoader[Seq[String]]] // configs.get has one implicit parameter that accepts ConfigLoader[Seq[String]] 
    
    when(configs.get[Seq[String]](any[String])(loader)).thenReturn(testData)
    

    【讨论】:

    • 谢谢!将模拟传递给隐式参数帮助我解决了问题
    【解决方案4】:

    尽管有正确的数量,但我看到了这个关于参数不匹配的错误...

    我意识到这是因为被存根的方法是静态的。当我将其转换为非静态时,它按预期工作。

    【讨论】:

    • 如果是 Strings 它的工作,那么 boolean 或 int 呢?
    【解决方案5】:

    供未来的读者阅读。这将为您节省大量时间。

    我们不能同时使用参数匹配器和原始/原始值。

    when(fooService.getResult("string",any(MyClass.class))).thenReturn(1); // will give error
    
    when(fooService.getResult(anyString(),any(MyClass.class))).thenReturn(1); // correct
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-23
      • 1970-01-01
      • 1970-01-01
      • 2022-07-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多