phpunit избегает аргументов конструктора для mock - PullRequest
80 голосов
/ 11 ноября 2008

Как избежать вызова phpunit конструктора для фиктивного объекта? В противном случае мне понадобится фиктивный объект в качестве аргумента конструктора, другой для этого и т. Д. API выглядит следующим образом:

getMock($className, $methods = array(), array $arguments = array(),
        $mockClassName = '', $callOriginalConstructor = TRUE,
        $callOriginalClone = TRUE, $callAutoload = TRUE)

Я не заставляю его работать. Он по-прежнему жалуется на аргумент конструктора, даже если для $callOriginalConstructor установлено значение false.

У меня только один объект в конструкторе, и это внедрение зависимостей. Так что я не думаю, что у меня там проблемы с дизайном.

Ответы [ 6 ]

135 голосов
/ 08 июня 2011

Вы можете использовать getMockBuilder вместо getMock:

$mock = $this->getMockBuilder('class_name')
    ->disableOriginalConstructor()
    ->getMock();

Подробнее см. В разделе «Проверка пар» в документации PHPUnit .

Несмотря на то, что вы можете сделать это, гораздо лучше не нужно. Вы можете реорганизовать свой код, чтобы вместо конкретного класса (с конструктором), который нужно было внедрить, вы зависели только от интерфейса. Это означает, что вы можете смоделировать или заглушить интерфейс, не сообщая PHPUnit об изменении поведения конструктора.

42 голосов
/ 10 марта 2009

Вот, пожалуйста:

    // Get a Mock Soap Client object to work with.
    $classToMock = 'SoapClient';
    $methodsToMock = array('__getFunctions');
    $mockConstructorParams = array('fake wsdl url', array());
    $mockClassName = 'MyMockSoapClient';
    $callMockConstructor = false;
    $mockSoapClient = $this->getMock($classToMock,
                                     $methodsToMock,
                                     $mockConstructorParams,
                                     $mockClassName,
                                     $callMockConstructor);
3 голосов
/ 08 марта 2013

В качестве дополнения я хотел прикрепить expects() вызовы к моему максируемому объекту, а затем вызвать конструктор. В PHPUnit 3.7.14 объект, который возвращается при вызове disableOriginalConstructor(), буквально является объектом.

// Use a trick to create a new object of a class
// without invoking its constructor.
$object = unserialize(
sprintf('O:%d:"%s":0:{}', strlen($className), $className)

К сожалению, в PHP 5.4 есть новая опция, которую они не используют:

ReflectionClass :: newInstanceWithoutConstructor

Поскольку это было недоступно, мне пришлось вручную отразить класс, а затем вызвать конструктор.

$mock = $this->getMockBuilder('class_name')
    ->disableOriginalConstructor()
    ->getMock();

$mock->expect($this->once())
    ->method('functionCallFromConstructor')
    ->with($this->equalTo('someValue'));

$reflectedClass = new ReflectionClass('class_name');
$constructor = $reflectedClass->getConstructor();
$constructor->invoke($mock);

Обратите внимание, что если functionCallFromConstruct равно protected, вам специально нужно использовать setMethods(), чтобы защищенный метод был поддельным Пример:

    $mock->setMethods(array('functionCallFromConstructor'));

setMethods() необходимо вызвать до вызова expect(). Лично я цепью это после disableOriginalConstructor(), но до getMock().

1 голос
/ 21 июля 2014

В качестве альтернативы вы можете добавить параметр к getMock , чтобы предотвратить вызов конструктора по умолчанию.

$mock = $this->getMock(class_name, methods = array(), args = array(), 
        mockClassName = '', callOriginalConstructor = FALSE);

Тем не менее, я думаю, что ответ dave1010 выглядит лучше, это только ради полноты.

1 голос
/ 02 декабря 2008

Возможно, вам нужно создать заглушку для передачи в качестве аргумента конструктора. Тогда вы можете разорвать эту цепочку фиктивных объектов.

0 голосов
/ 09 декабря 2008

PHPUnit предназначен для вызова конструктора на макетируемых объектах; Чтобы предотвратить это, вы должны либо:

  1. Внедрение фиктивного объекта в качестве зависимости в объект, с которым у вас возникают проблемы
  2. Создайте тестовый класс, расширяющий класс, который вы пытаетесь вызвать, который не вызывает родительский конструктор
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...