使用PHPUnit,我正在嘲笑pdo,但我正在尝试找到一种方法来准备多个数据库查询语句。
$pdo = $this->getPdoMock();
$stmt = $this->getPdoStatementMock($pdo);
$pdo->expects($this->any())
->method('prepare')
->with($this->equalTo($title_query))
->will($this->returnValue($stmt));
$title_stmt = $pdo->prepare($title_query);
$desc_stmt = $pdo->prepare($desc_query);
我想为onConsecutiveCalls传递类似于“with”方法的东西,所以我可以准备多个语句,如上所示。 你会怎么做呢?
答案 0 :(得分:22)
您可以通过使用$this->at()
而不是$this->any()
编写单独的期望来匹配相同方法的连续调用:
$pdo->expects($this->at(0))
->method('prepare')
->with($this->equalTo($title_query))
->will($this->returnValue($stmt));
$pdo->expects($this->at(1))
->method('prepare')
->with($this->equalTo($desc_query))
->will($this->returnValue($stmt));
$title_stmt = $pdo->prepare($title_query);
$desc_stmt = $pdo->prepare($desc_query);
答案 1 :(得分:15)
PHPUnit 4.1获得了一个新方法withConsecutive()
。来自Test Double Chapter:
class FooTest extends PHPUnit_Framework_TestCase
{
public function testFunctionCalledTwoTimesWithSpecificArguments()
{
$mock = $this->getMock('stdClass', array('set'));
$mock->expects($this->exactly(2))
->method('set')
->withConsecutive(
array($this->equalTo('foo'), $this->greaterThan(0)),
array($this->equalTo('bar'), $this->greaterThan(0))
);
$mock->set('foo', 21);
$mock->set('bar', 48);
}
}
withConsecutive()
的每个参数都是对指定方法的一次调用。
答案 2 :(得分:10)
使用更新版本的PHPUnit,可以简化接受的答案。
另外,虽然它与原始问题没有直接关系,但您可以通过willReturnOnConsecutiveCalls
方法为每个方法调用轻松提供不同的返回值。
$pdo->expects($this->exactly(2))
->method('prepare')
->withConsecutive(
$this->equalTo($title_query),
$this->equalTo($desc_query)
)
->willReturnOnConsecutiveCalls(
$stmt, // returned on the 1st call to prepare()
$stmt // returned on the 2nd call to prepare()
);
答案 3 :(得分:3)
我发现的唯一一个与你问的相似的是使用'at':
$mock->expects($this->at(0))->method // etc
$mock->expects($this->at(1))->method // etc
因此,您可以在第一次调用(0)时设置预期,第二次调整等等。
答案 4 :(得分:0)
有几个人注意到,($ index)可用于调用方法的特定实例。 David H.和Vika澄清说$ index对所有模拟对象的方法进行ALL调用。
此外,值得注意的是PHPunit文档的Test Doubles Chapter有关于此的警告说明。它指出使用at()应该谨慎,因为它可能导致脆弱的测试,这些测试过于依赖于具体的实现。
答案 5 :(得分:0)
我使用dataProvider并且需要可变数量的已执行查询,我可以使用它来填充我的提供程序,我想提供一个应该执行的查询数组。
withConsecutive
的问题在于它需要可变数量的数组,每个数组都是一个参数数组。
我使用以下代码解决了这个问题,感觉" hacky"但是有效:
$withConsecutiveArgs = [
[$this->equalTo($title_query)],
[$this->equalTo($desc_query)],
...,
N queries
];
$withConsecutiveReturns = [
$title_stmt,
$desc_stmt,
...,
N returns
];
$methodMock = $pdo->expects($this->exactly(count($args))->method('prepare');
$methodMock->getMatcher()->parametersMatcher = new \PHPUnit_Framework_MockObject_Matcher_ConsecutiveParameters($withConsecutiveArgs);
$methodMock->will(new \PHPUnit_Framework_MockObject_Stub_ConsecutiveCalls($withConsecutiveReturns));
$title_stmt = $pdo->prepare($title_query);
$desc_stmt = $pdo->prepare($desc_query);
...
$N_s_stmt = $pdo->prepare($N_s_query);
我希望它能够在未来版本的PhpUnit中正确发展(这是不确定的,因为我依赖于lib的内部,但这是进行单元测试的全部要点,我可能需要重构它,但生产将会不受此影响)