我有一个方法 <?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
?或者这两者甚至有任何关系,因为其中一个是匹配器而另一个只是一个值?
答案 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);