Intereting Posts
Создайте скрипт загрузки изображений PHP для переименования и изменения размера Как заменить вкладки пробелами внутри переменных в PHP? Являются ли PHP preg_functions многобилетными безопасными? Повторяющиеся символы регулярного выражения Php Разбор JSON-объекта в PHP с помощью json_decode Отладка подключения порта IDE к XDebug: «Ожидание подключения» Проблема с поплавками! (в PHP) Почему Laravel / Eloquent не может использовать JOIN для Eager Loading? Как отправить запрос curl с сертификатом pem через PHP? Проверьте, существует ли экземпляр класса, если не создать экземпляр Арабский язык в php / mysql появляется «????» вопросительные знаки в html Разделить платеж Paypal на две учетные записи В PHP, как я могу добавить нумерованную цифровую строку и сохранить нулевое дополнение? Заменить диакритические символы «эквивалентным» ASCII в PHP? настройка формы как функция во внешнем php-файле

Метод тестирования phpunit, который вызывает другие методы класса, которые требуют макета

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

Я хочу издеваться над этим методом, но все равно выполняю метод, который я тестирую как есть, только с измененным значением, возвращенным из вызова другому методу.

Я отбросил этот пример, чтобы сделать его максимально простым.

class MyClass { // I want to test this method, but mock the handleValue method to always return a set value. public function testMethod($arg) { $value = $arg->getValue(); $this->handleValue($value); } // This method needs to be mocked to always return a set value. public function handleValue($value) { // Do a bunch of stuff... $value += 20; return $value; } } 

Моя попытка написать тесты.

 class MyClassTest extends \PHPUnit_Framework_TestCase { public function testTheTestMethod() { // mock the object that is passed in as an arg $arg = $this->getMockBuilder('SomeEntity')->getMock(); $arg->expects($this->any()) ->method('getValue') ->will($this->returnValue(10)); // test handle document() $myClass = new MyClass(); $result = $myClass->testMethod($arg); // assert result is the correct $this->assertEquals($result, 50); } } 

Я пробовал издеваться над объектом MyClass, но когда я это делаю и вызываю testMethod, он всегда возвращает null. Мне нужен способ издеваться над одним методом, но остальная часть объекта не повреждена.

Solutions Collecting From Web of "Метод тестирования phpunit, который вызывает другие методы класса, которые требуют макета"

Вы можете издеваться над классом, который вы тестируете, и указать метод, который вы хотите высмеять.

 $mock = $this->getMockBuilder('MyClass') ->setMethods(array('handleValue')) ->getMock(); $mock->expects($this->once()) ->method('handleValue') ->will($this->returnValue(23)) //Whatever value you want to return 

Однако ИМО это не лучшая идея для ваших тестов. Тестирование таким образом сделает рефакторинг намного сложнее. Вы указываете реализацию класса, а не поведение, которое должен иметь класс. Если handleValue выполняет много сложной работы, что затрудняет тестирование, подумайте о том, чтобы переместить логику в отдельный класс и ввести ее в свой класс. Затем вы можете создать макет этого класса и передать его testMethod . Это даст вам дополнительное преимущество в том, чтобы сделать MyClass более расширяемым, если handleValue должен адаптировать свое поведение.

http://www.oodesign.com/strategy-pattern.html

Как правило, вы не должны издеваться над тестируемой системой.

Вы можете указать, какие методы высмеивать (частичный макет) с помощью setMethods() :

  // Let's do a `partial mock` of the object. By passing in an array of methods to `setMethods` // we are telling PHPUnit to only mock the methods we specify, in this case `handleValue()`. $csc = $this->getMockBuilder('Lightmaker\CloudSearchBundle\Controller\CloudSearchController') ->setConstructorArgs($constructor) ->setMethods(array('handleValue')) ->getMock(); // Tell the `handleValue` method to return 'bla' $csc->expects($this->any()) ->method('handleValue') ->with('bla'); 

Любые другие методы в классе, не указанном в массиве, который вы передаете setMethods() будут выполняться как есть. Если вы не используете setMethods все методы вернут NULL если вы специально их не установили.