Скажем, я хочу заменить метод в объекте, который получает базу данных из базы данных, на метод с предварительно заполненными данными. Как бы я это сделал?
В соответствии с https://phpunit.de/manual/current/en/test-doubles.html …
setMethods (массив $ методов) может быть вызван для объекта Mock Builder для
указать методы, которые должны быть заменены настраиваемым тестом
двойной. Поведение других методов не изменилось. Если вы позвоните
setMethods (NULL), тогда никакие методы не будут заменены.
Отлично. Так что это говорит phpunit, какие методы я хочу заменить, но где мне сказать, чем я их заменяю?
Я нашел этот пример:
protected function createSSHMock()
{
return $this->getMockBuilder('Net_SSH2')
->disableOriginalConstructor()
->setMethods(array('__destruct'))
->getMock();
}
Отлично — так __destruct
метод заменяется. Но чем его заменяют? Я понятия не имею. Вот источник для этого:
https://github.com/phpseclib/phpseclib/blob/master/tests/Unit/Net/SSH2Test.php
С методом, который ничего не делает, но чье поведение вы можете настроить позже. Хотя я не уверен, что вы полностью поняли, как работает издевательство.
Вы не должны дразнить класс, который вы тестируете, вы должны дразнить объекты, на которые опирается тестируемый класс. Например:
// class I want to test
class TaxCalculator
{
public function calculateSalesTax(Product $product)
{
$price = $product->getPrice();
return $price / 5; // whatever calculation
}
}
// class I need to mock for testing purposes
class Product
{
public function getPrice()
{
// connect to the database, read the product and return the price
}
}
// test
class TaxCalculatorTest extends \PHPUnit_Framework_TestCase
{
public function testCalculateSalesTax()
{
// since I want to test the logic inside the calculateSalesTax method
// I mock a product and configure the methods to return some predefined
// values that will allow me to check that everything is okay
$mock = $this->getMock('Product');
$mock->method('getPrice')
->willReturn(10);
$taxCalculator = new TaxCalculator();
$this->assertEquals(2, $taxCalculator->calculateSalesTax($mock));
}
}
Ваш тест макетирует именно тот класс, который вы пытаетесь протестировать, что может быть ошибкой, поскольку некоторые методы могут быть переопределены во время макетирования.
Других решений пока нет …