如何处理"任何其他价值"与Mockito?

时间:2015-12-09 05:00:59

标签: java mockito

我有一个方法 <?php $con=mysqli_connect("localhost","my_user","my_password","my_db"); // Check connection if (mysqli_connect_errno()) { echo "Failed to connect to MySQL: " . mysqli_connect_error(); } $sql = "SELECT Lastname FROM Persons ORDER BY LastName;"; $sql .= "SELECT Country FROM Customers"; // Execute multi query if (mysqli_multi_query($con,$sql)) { do { // Store first result set if ($result=mysqli_store_result($con)) { // Fetch one and one row while ($row=mysqli_fetch_row($result)) { printf("%s\n",$row[0]); } // Free result set mysqli_free_result($result); } } while (mysqli_next_result($con)); } mysqli_close($con); ?> 的界面Foo,我想用Mockito模拟。如果我传入int Foo.bar(int),我希望模拟方法返回99,但所有其他值都会抛出异常。我可以这样做吗?

1

换句话说,final Foo foo = mock(Foo.class); when(foo.bar(1)).thenReturn(99); when(foo.bar(anyInt())).thenThrow(new IllegalArgumentException()); 优先于1吗?我不希望它为anyInt()抛出异常。 docs表示对于多个定义,最后一个定义更重要,但我无法判断这是否意味着相同的参数。如果它适用于此处,我是否需要首先定义通配符1?或者这两者甚至有任何关系,因为其中一个是匹配器而另一个只是一个值?

1 个答案:

答案 0 :(得分:22)

您有两种选择:匹配&#34;任何值,但一个&#34;,并覆盖存根。 (我想你也可以使用一个复杂的自定义行为的答案,但对于像这样的情况来说这有点过头了。)

对除给定值之外的任何值

进行存根

Mockito的AdditionalMatchers课程提供了许多有用的匹配器,包括not等运算符。这将允许您为除特定值(或表达式)之外的所有值设置行为。

when(foo.bar(1)).thenReturn(99);
when(foo.bar(not(eq(1)))).thenThrow(new IllegalArgumentException());

请注意,运算符必须与匹配器一起使用而不是值,可能需要Matchers.eq作为明确的equals匹配器,因为Mockito的argument matcher stack

/* BAD */  when(foo.bar(not(  1  ))).thenThrow(new IllegalArgumentException());
/* GOOD */ when(foo.bar(not(eq(1)))).thenThrow(new IllegalArgumentException());

覆盖存根

对于存根,最后定义的匹配链获胜。这允许您在@Before方法中设置常规测试夹具行为,并在您希望的情况下在单个测试用例中覆盖它,但也暗示订单在您的存根调用中很重要。

when(foo.baz(anyInt())).thenReturn("A", "B");  /* or .thenReturn("A").thenReturn("B"); */
when(foo.baz(9)).thenReturn("X", "Y");

foo.baz(6); /* "A" because anyInt() is the last-defined chain */
foo.baz(7); /* "B" as the next return value of the first chain */
foo.baz(8); /* "B" as Mockito repeats the final chain action forever */

foo.baz(9); /* "X" because the second chain matches for the value 9 */
foo.baz(9); /* "Y" forever because the second chain action still matches */

因此,你永远不应该按照问题中列出的顺序看到两个存根,因为如果一般匹配紧跟在特定匹配之后,那么特定匹配将永远不会被使用(也可能被删除)。

请注意,在覆盖间谍或危险的存根行为时,您有时需要将语法更改为doAnswer。 Mockito知道不计算对when的调用进行验证或推进thenVerb链,但异常仍可能导致测试失败。

/* BAD: the call to foo.bar(1) will throw before Mockito has a chance to stub it! */
when(foo.bar(anyInt())).thenThrow(new IllegalArgumentException());
when(foo.bar(1)).thenReturn(99);

/* GOOD: Mockito has a chance to deactivate behavior during stubbing. */
when(foo.bar(anyInt())).thenThrow(new IllegalArgumentException());
doReturn(99).when(foo).bar(1);