Comment éviter que phpunit doive appeler le constructeur pour un objet simulé? Sinon, j'aurais besoin d'un objet simulé comme argument constructeur, un autre pour cela, etc. L'API semble être comme ceci:
getMock($className, $methods = array(), array $arguments = array(),
$mockClassName = '', $callOriginalConstructor = TRUE,
$callOriginalClone = TRUE, $callAutoload = TRUE)
Je ne le fais pas fonctionner. Il se plaint toujours de l'argument constructeur, même avec $callOriginalConstructor
défini sur false.
Je n'ai qu'un seul objet dans le constructeur et c'est une injection de dépendance. Je ne pense donc pas que j'ai un problème de conception là-bas.
Vous pouvez utiliser getMockBuilder
au lieu de simplement getMock
:
$mock = $this->getMockBuilder('class_name')
->disableOriginalConstructor()
->getMock();
Voir la section sur "Test Doubles" dans documentation de PHPUnit pour plus de détails.
Bien que vous puissiez le faire, il est préférable de ne pas en avoir besoin. Vous pouvez refactoriser votre code, donc au lieu d'une classe concrète (avec un constructeur) devant être injectée, vous ne dépendez que d'une interface. Cela signifie que vous pouvez simuler ou bloquer l'interface sans avoir à dire à PHPUnit de modifier le comportement du constructeur.
Voici:
// 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);
En complément, je voulais attacher des appels expects()
à mon objet simulé, puis appeler le constructeur. Dans PHPUnit 3.7.14, l'objet renvoyé lorsque vous appelez disableOriginalConstructor()
est littéralement un objet.
// 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)
Malheureusement, dans PHP 5.4 il y a une nouvelle option qu'ils n'utilisent pas:
ReflectionClass :: newInstanceWithoutConstructor
Comme cela n'était pas disponible, j'ai dû refléter manuellement la classe, puis invoquer le constructeur.
$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);
Notez que si functionCallFromConstruct
est protected
, vous devez spécifiquement utiliser setMethods()
pour que la méthode protégée soit mockée. Exemple:
$mock->setMethods(array('functionCallFromConstructor'));
setMethods()
doit être appelé avant l'appel de expect()
. Personnellement, je l'enchaîne après disableOriginalConstructor()
mais avant getMock()
.
Vous devez peut-être créer un stub à passer comme argument constructeur. Ensuite, vous pouvez briser cette chaîne d'objets fictifs.
Alternativement, vous pouvez ajouter un paramètre à getMock pour empêcher l'appel du constructeur par défaut.
$mock = $this->getMock(class_name, methods = array(), args = array(),
mockClassName = '', callOriginalConstructor = FALSE);
Pourtant, je pense que la réponse de dave1010 est plus belle, c'est juste pour être complet.
PHPUnit est conçu pour appeler le constructeur sur des objets simulés; pour éviter cela, vous devez soit: