есть ли в phpunit метод, аналогичный onconsecutivecalls, для использования внутри метода with? - PullRequest
14 голосов
/ 16 марта 2011

Используя 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 для метода «с», чтобы я мог подготовить несколько операторов, как показано выше. Как бы вы поступили так?

Ответы [ 6 ]

22 голосов
/ 16 марта 2011

Вы можете сопоставить последовательные вызовы одного и того же метода, написав отдельные ожидания с $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);
15 голосов
/ 02 июня 2014

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() предназначен для одного вызова указанного метода.

10 голосов
/ 25 марта 2016

В более поздних версиях 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 голосов
/ 16 марта 2011

Единственное, что я нашел, похожее на то, что вы спрашиваете, это использовать 'at':

$mock->expects($this->at(0))->method // etc
$mock->expects($this->at(1))->method // etc

Таким образом, вы устанавливаете ожидания в первый раз, когда он называется (в 0), во второй раз и т. Д.

1 голос
/ 14 декабря 2013

Несколько человек отметили, что at ($ index) может использоваться для конкретных случаев вызова метода.Дэвид Х. и Вика пояснили, что $ index считает ВСЕ обращения ко ВСЕМ смоделированным методам объекта.

Кроме того, стоит отметить, что глава Test Doubles *1004* документации PHPunitпредупреждение об этом.Он указывает, что использование at () должно выполняться с осторожностью, поскольку это может привести к хрупким тестам, которые слишком сильно зависят от конкретной реализации.

0 голосов
/ 12 октября 2017

Я использую dataProvider и мне нужно переменное количество выполненных запросов, которые я могу использовать для заполнения своего провайдера, я хочу предоставить массив запросов, которые должны быть выполнены. Проблема с withConsecutive состоит в том, что он принимает переменное число массивов, каждый из которых представляет собой массив аргументов.

Я решил это с помощью следующего кода, это выглядит "хакерским", но работает:

$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 (что неясно, так как я полагаюсь на внутренние компоненты библиотеки, но в этом весь смысл модульного тестирования, возможно, мне придется его реорганизовать, но производство не пострадает от этого )

...