PHPUnit - несколько тупиков того же класса

Я - тесты сборочного узла для класса Foo, и я довольно плохо знаком с поблочным тестированием.

Ключевой компонент моего класса является экземпляром BarCollection который содержит много Bar объекты. Один метод в Foo выполняет итерации через набор и называет пару методов на каждом Bar объект в наборе. Я хочу использовать тупиковые объекты генерировать ряд ответов для моего тестового класса. Как я делаю Bar тупиковый класс возвращает различные значения, поскольку я выполняю итерации? Я пытаюсь сделать что-то вдоль этих строк:

$stubs = array();
foreach ($array as $value) {
    $barStub = $this->getMock('Bar');
    $barStub->expects($this->any())
            ->method('GetValue')
            ->will($this->returnValue($value));
    $stubs[] = $barStub;
}
// populate stubs into `Foo`

// assert results from `Foo->someMethod()`

Так Foo->someMethod() произведет данные на основе результатов, которые они получают из Bar объекты. Но это дает мне следующую ошибку каждый раз, когда массив - дольше, чем один:

There was 1 failure:

1) testMyTest(FooTest) with data set #2 (array(0.5, 0.5))
Expectation failed for method name is equal to <string:GetValue> when invoked zero or more times.
Mocked method does not exist.
/usr/share/php/PHPUnit/Framework/MockObject/Mock.php(193) : eval()'d code:25

Одна мысль, которую я имел, состояла в том, чтобы использовать ->will($this->returnCallback()) для вызова метода обратного вызова но я не знаю, как указать к обратному вызову который Bar объект выполняет вызов (и следовательно что ответ дать).

Другая идея состоит в том, чтобы использовать onConsecutiveCalls() метод или что-то как он, чтобы сказать моему тупику возвращаться 1 в первый раз, 2 во второй раз, и т.д., но я не уверен точно, как сделать это. Я также обеспокоен, что, если мой класс когда-нибудь делает что-нибудь кроме заказанного повторения на наборе, у меня не будет способа протестировать его.

9
задан keithjgrant 26 March 2010 в 23:23
поделиться

3 ответа

К сожалению, я не уверен, что вы можете решить свой вопрос с помощью getMock () , но мой опыт работы с getMock () сам по себе тонкий.

Единственное, что я могу придумать навскидку, но не зная вашего класса Bar , это может не помочь: третий параметр getMock () позволяет передавать аргументы конструктора (как множество).

Я бы создал свой собственный макет-класс, расширяющий Bar в качестве помощника по тестированию (причудливое название для «просто еще одного класса, который используется только в тестах»), который делает именно то, что мне нравится, и внедряет серию из них в ваш Объект Foo . Это дает вам весь необходимый контроль, поскольку вы можете полностью заменить рассматриваемые методы, чего не делает getMock () . Конечно, это также означает, что вы не тестируете класс Bar в этом тесте, что может быть не тем, что вам нужно - хотя я все равно рекомендовал бы написать отдельный тестовый класс для каждого тестируемого класса, но есть случаи где это излишне пуристическое.

$stubs = array();
foreach ($array as $value) {
    $stubs[] = new MyBarTestHelper($value);
}

Кроме того, я искренне удивлен, что вы видите описанное исключение только тогда, когда у вас более одного элемента массива. Я заметил, что PHPUnit на самом деле ожидает, что вы объявите любой метод, который вы хотите, чтобы он мог отслеживать, как параметр getMock () , и в противном случае будет тупо вывести ошибку, поскольку по сути то, что он делает внутри, создает свои собственное расширение класса, заключающее в оболочку каждый метод, который вы явно объявляете, с логикой, которая позволяет ему определять, был ли он вызван (= добавление имени метода в логический список).

Нарисуйте меня наивным (серьезно, наверное, я, я новичок в тестах), но посмотрите, поможет ли вам это хоть как-то:

$stubs = array();
foreach ($array as $value) {
    $barStub = $this->getMock('Bar', array('GetValue'));
    $barStub->expects($this->any())
            ->method('GetValue')
            ->will($this->returnValue($value));
    $stubs[] = $barStub;
}
2
ответ дан 5 December 2019 в 02:07
поделиться

Это должно удовлетворять требованию о возврате серии значений в том порядке, в котором они вызываются, если вам удобно использовать global. Он не знает, какой Bar вызывается, но если каждый Bar вызывается Foo один раз по порядку, тогда не должно быть слишком сложно заполнить тестовые данные.

$barTestData = array('empty',1,2,3,4,5,6);

function barDataCallback(){
    global $barTestData;
    return next($barTestData);
}
0
ответ дан 5 December 2019 в 02:07
поделиться

Я заметил, что в вашем коде есть лишняя скобка после "-> method ('GetValue')". Не знаю, скопировали вы это или нет.

0
ответ дан 5 December 2019 в 02:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: