Mockito如何处理thenReturn块中具有多个参数的重叠匹配器 [英] How does Mockito handle overlapping matchers with multiple arguments in the thenReturn block

查看:646
本文介绍了Mockito如何处理thenReturn块中具有多个参数的重叠匹配器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个测试代码块,尝试在一般情况下在后续调用中返回两个值,但在特定情况下仅返回与该情况相关的值.该代码看起来像:

I've got a block of test code that is attempting to, in the generic case return two values on subsequent calls, but in specific cases only return the value associated with that case. The code looks something like:

when(mockObject.method(anyString())).thenReturn(string1, string2);
when(mockObject.method(eq("expectedInput1"))).thenReturn(string1);
when(mockObject.method(eq("expectedInput2"))).thenReturn(string2);

预期的行为是,分别调用mockObject.method("foo")mockObject.method("bar")时应分别返回string1string2,但是测试实际上看到了string2的两个响应.这是Mockito中的错误吗?还是我误解了Mockito模式匹配.

The expected behavior is that when calling mockObject.method("foo") and mockObject.method("bar"), string1 and string2 should be returned respectively, but the test is actually seeing two responses of string2. Is this a bug in Mockito? Or am I misunderstanding Mockito pattern matching.

我的假设是要匹配的最后一个模式是返回的内容,但是在执行该过程时,Mockito是否会分别处理第一个thenReturn块中的每个参数?有什么办法可以解决这个问题?

My assumption was that the last pattern to match is what is returned, but when going through that process does Mockito treat each argument in the first thenReturn block separately? Is there any way to get around this behavior?

当我注释掉第二个when调用时,模拟行为的行为符合预期,因此我假设重叠匹配器行为有一些特定之处.

When I comment out the second two when calls, the mocks behave as expected, so I'm assuming there is something specific about the overlapping matcher behavior.

这是Mockito版本1.9.5

推荐答案

我今天遇到了这个问题.这是由于调用模拟程序来建立存根而实际上消耗了已经存在的存根.

I had this problem today. It is caused by calls to the mock to set up stubbing actually consuming the stubbing already in place.

在此示例中,将第一行更改为

In this example, change the first line to

when(mock.call(anyString())).thenReturn("","",string1,string2)

设置其他模拟返回时,这将给您两个空白响应,而将string1作为第一个有用的返回值.

This will give you two blank responses when you set up your other mock returns, leaving string1 as the first useful return value.

请尝试我认为可能没有这些问题的doReturn替代方法:

Try also the doReturn alternative which I think may not have these issues:

doReturn(string1,string2).when(mock).call(anyString());

这在设置过程中使用存根的方式有所不同.

This uses the stub differently during setup.

因此,我对此进行了更多研究.根据OP的问题,这是我正在使用的功能:

So I did some more research on this. Here's the function I was playing with, based on the OP's question:

    Function<String, String> function = mock(Function.class);
    when(function.apply(anyString())).thenReturn("A","B","C");
    when(function.apply("Jim")).thenReturn("Jim");
    when(function.apply("Bob")).thenReturn("Bob");

    assertThat(function.apply("Jim")).isEqualTo("Jim");
    assertThat(function.apply("Bob")).isEqualTo("Bob");
    assertThat(function.apply("")).isEqualTo("A");
    assertThat(function.apply("")).isEqualTo("B");
    assertThat(function.apply("")).isEqualTo("C");
    assertThat(function.apply("")).isEqualTo("C");

上面的操作在isEqualTo("A")处失败,因为这两个调用JimBob的模拟程序的调用消耗了提供给anyString()的列表中的返回值.

The above fails at isEqualTo("A") because the two calls to set up the mocks for Jim and Bob consume return values from the list provided to anyString().

您可能会想对when子句重新排序,但这失败了,因为anyString()取代了特殊情况,所以也失败了.

You might be tempted to reorder the when clauses, but that fails, because the anyString() supersedes the special cases, so that fails too.

上述DOES的以下版本按预期工作:

The following version of the above DOES work as expected:

    when(function.apply(anyString())).thenReturn("A","B","C");

    doReturn("Jim")
        .when(function)
        .apply("Jim");
    doReturn("Bob")
        .when(function)
        .apply("Bob");

    assertThat(function.apply("Jim")).isEqualTo("Jim");
    assertThat(function.apply("Bob")).isEqualTo("Bob");
    assertThat(function.apply("")).isEqualTo("A");
    assertThat(function.apply("")).isEqualTo("B");
    assertThat(function.apply("")).isEqualTo("C");
    assertThat(function.apply("")).isEqualTo("C");

这是因为doReturn技术旨在修改飞行中已存在的模拟,实际上并不涉及调用模拟中的方法来建立模拟.

This is because the doReturn technique, which is intended for modifying pre-existing mocks in flight, doesn't actually involve calling the method on the mock to set up the mocking.

您可以使用doReturn进行所有设置,而不是在when ... thenReturndoReturn .. when .. function()之间混合使用.碰巧的是,这有点丑陋:

You could use doReturn for all setup, rather than mixing between when...thenReturn and doReturn..when..function(). As it happens, that's a bit uglier:

    doReturn("A").doReturn("B").doReturn("C")
        .when(function)
        .apply(anyString());

没有方便的varargs函数来让您依次指定多个收益.上面的代码已经过测试,并且可以正常工作.

There's no convenient varargs function to let you specify multiple returns in sequence. The above has been tested and does work, though.

这篇关于Mockito如何处理thenReturn块中具有多个参数的重叠匹配器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆