Wie kann vermieden werden, dass phpunit den Konstruktor für ein Scheinobjekt aufrufen muss? Andernfalls würde ich ein Mock-Objekt als Konstruktor-Argument benötigen, ein anderes dafür usw. Die API scheint so zu sein:
getMock($className, $methods = array(), array $arguments = array(),
$mockClassName = '', $callOriginalConstructor = TRUE,
$callOriginalClone = TRUE, $callAutoload = TRUE)
Ich bringe es nicht zum Laufen. Es beschwert sich immer noch über das Konstruktorargument, auch mit $callOriginalConstructor
auf false gesetzt.
Ich habe nur ein Objekt im Konstruktor und es ist eine Abhängigkeitsinjektion. Ich glaube also nicht, dass ich dort ein Designproblem habe.
Sie können getMockBuilder
anstelle von getMock
verwenden:
$mock = $this->getMockBuilder('class_name')
->disableOriginalConstructor()
->getMock();
Weitere Informationen finden Sie im Abschnitt zu "Test Doubles" in Dokumentation von PHPUnit .
Obwohl Sie dies tun können, ist es viel besser, dies nicht zu müssen. Sie können Ihren Code umgestalten, sodass Sie anstatt einer konkreten Klasse (mit einem Konstruktor), die eingefügt werden muss, nur von einer Schnittstelle abhängig sind. Dies bedeutet, dass Sie die Schnittstelle verspotten oder stummschalten können, ohne PHPUnit anweisen zu müssen, das Konstruktorverhalten zu ändern.
Bitte schön:
// 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);
Als Ergänzung wollte ich expects()
Aufrufe an mein verspottetes Objekt anhängen und dann den Konstruktor aufrufen. In PHPUnit 3.7.14 ist das Objekt, das beim Aufruf von disableOriginalConstructor()
zurückgegeben wird, buchstäblich ein Objekt.
// 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)
Leider gibt es in PHP 5.4 eine neue Option, die sie nicht verwenden:
ReflectionClass :: newInstanceWithoutConstructor
Da dies nicht verfügbar war, musste ich die Klasse manuell widerspiegeln und dann den Konstruktor aufrufen.
$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);
Hinweis: Wenn functionCallFromConstruct
protected
ist, müssen Sie setMethods()
verwenden, damit die geschützte Methode verspottet wird. Beispiel:
$mock->setMethods(array('functionCallFromConstructor'));
setMethods()
muss vor dem expect()
-Aufruf aufgerufen werden. Persönlich verkette ich dies nach disableOriginalConstructor()
, aber vor getMock()
.
Möglicherweise müssen Sie einen Stub erstellen, der als Konstruktorargument übergeben wird. Dann können Sie diese Kette von Scheinobjekten durchbrechen.
Alternativ können Sie getMock einen Parameter hinzufügen, um den Aufruf des Standardkonstruktors zu verhindern.
$mock = $this->getMock(class_name, methods = array(), args = array(),
mockClassName = '', callOriginalConstructor = FALSE);
Trotzdem finde ich die Antwort von dave1010 schöner, dies ist nur der Vollständigkeit halber.
PHPUnit ruft den Konstruktor für verspottete Objekte auf. Um dies zu verhindern, sollten Sie entweder: