Используя 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», поэтому я могу подготовить несколько операторов, как показано выше. Как бы вы это сделали?
Вы можете сопоставлять последовательные вызовы одного и того же метода, записывая отдельные ожидания с помощью $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);
PHPUnit 4.1 получил новый метод withConsecutive()
. Из тестовой двойной главы :
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()
предназначен для одного вызова указанного метода.
В более поздних версиях 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() );
Единственное, что я нашел, похожий на то, что вы просите, – это «at»:
$mock->expects($this->at(0))->method // etc $mock->expects($this->at(1))->method // etc
Таким образом, вы устанавливаете ожидания в первый раз, когда он называется (в 0), второй раз и так далее.
Несколько человек отметили, что в ($ index) можно использовать для конкретных экземпляров вызовов метода. Дэвид Х. и Вика пояснили, что $ index подсчитывает ВСЕ вызовы ВСЕМ издеваемым методам объекта.
Кроме того, возможно, стоит отметить, что в главе «Двухместные пары» документации PHPunit есть предупреждающая записка об этом. Он указывает, что использование at () следует делать с осторожностью, поскольку это может привести к хрупким испытаниям, которые слишком сильно зависят от конкретной реализации.
Я использую dataProvider и нуждаюсь в переменном количестве выполненных запросов, которые я могу использовать для заполнения моего провайдера, я хочу предоставить массив запросов, которые должны быть выполнены. Проблема с withConsecutive
заключается в том, что он принимает переменное количество массивов, каждый из которых представляет собой массив аргументов.
Я решил это с помощью кода follwing, это чувствует себя «взломанным», но работает:
$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, но в этом весь смысл проведения модульного теста, возможно, мне придется его реорганизовать, но производство не пострадает от этого)