phpunit vermeidet Konstruktorargumente für mock

Lesezeit: 4 Minuten

Wie kann vermieden werden, dass phpunit den Konstruktor für ein Scheinobjekt aufrufen muss? Ansonsten bräuchte ich ein Mock-Objekt als Konstruktor-Argument, 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 bekomme es nicht zum Laufen. Es beschwert sich immer noch über das Konstruktorargument, sogar mit $callOriginalConstructor auf falsch setzen.

Ich habe nur ein Objekt im Konstruktor und es ist eine Abhängigkeitsinjektion. Ich glaube also nicht, dass ich da ein Designproblem habe.

Benutzer-Avatar
dave1010

Sie können verwenden getMockBuilder statt nur getMock:

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

Siehe den Abschnitt über “Testdoppel” in Dokumentation von PHPUnit für Details.

Obwohl Sie dies tun können, ist es viel besser, es nicht zu müssen. Sie können Ihren Code so umgestalten, dass Sie statt einer konkreten Klasse (mit einem Konstruktor), die injiziert werden muss, nur von einer Schnittstelle abhängen. Das bedeutet, dass Sie die Schnittstelle mocken oder stubben können, ohne PHPUnit anweisen zu müssen, das Konstruktorverhalten zu ändern.

  • Das funktioniert super für mich. Es sollte aber Beispiel 10.3 sein. Ich habe versucht, den Beitrag zu bearbeiten, aber SO hat ihn zurückgewiesen, weil er zu kurz war.

    – Matthew

    31. Mai 2012 um 13:34 Uhr

  • Danke @Lytithwyn. Antwort aktualisiert.

    – dave1010

    31. Mai 2012 um 15:14 Uhr

Benutzer-Avatar
Matthäus Purdon

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);

  • Das scheint fast das zu sein, was ich will. Ich möchte getMock nur mit der zu verspottenden Klasse und dem $callMockConstructor aufrufen. Wie? etwa so: $this->getMock($classToMock, $callMockConstructor). Das einzige, was mir einfällt, ist, in die Quelle von PHPUnit zu gehen und sie auf default = false zu ändern.

    – Gutzofter

    16. April 2010 um 18:53 Uhr

  • Ich habe den Standard in testcase.php auf false geändert. Sie würden denken, dass es standardmäßig auf “false” gesetzt wäre. Einen Konstrukteur zu verspotten scheint sehr seltsam

    – Gutzofter

    16. April 2010 um 19:15 Uhr

  • Ausgezeichnete Antwort. Genau das, wonach ich gesucht habe

    – Hades

    18. Januar 2013 um 0:19 Uhr

Benutzer-Avatar
Wesley Gonçalves

Diese Frage ist etwas alt, aber für neue Besucher können Sie sie mit der createMock Methode (früher als createTestDouble und eingeführt in v5.4.0).

$mock = $this->createMock($className);

Wie Sie im folgenden Code sehen können, der aus der extrahiert wurde PHPUnit\Framework\TestCase Klasse (in phpunit/src/framework/TestCase.php), Es wird im Grunde ein Scheinobjekt erstellt, ohne den ursprünglichen Konstruktor aufzurufen.

/** PHPUnit\Framework\TestCase::createMock method */
protected function createMock(string $originalClassName): MockObject
{
    return $this->getMockBuilder($originalClassName)
                ->disableOriginalConstructor()
                ->disableOriginalClone()
                ->disableArgumentCloning()
                ->disallowMockingUnknownTypes()
                ->getMock();
}

Benutzer-Avatar
Steve Tauber

Als Nachtrag wollte ich anhängen expects() ruft mein verspottetes Objekt auf und ruft dann den Konstruktor auf. In PHPUnit 3.7.14 das Objekt, das beim Aufruf zurückgegeben wird disableOriginalConstructor() ist 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, ggf functionCallFromConstruct ist protectedmüssen Sie ausdrücklich verwenden setMethods() damit die geschützte Methode verspottet wird. Beispiel:

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

setMethods() muss vorher angerufen werden expect() Anruf. Ich persönlich kette das nach disableOriginalConstructor() Aber vorher getMock().

Benutzer-Avatar
Hans Wouters

Alternativ können Sie einen Parameter hinzufügen getMock 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 nur der Vollständigkeit halber.

Benutzer-Avatar
Glen Moos

Möglicherweise müssen Sie einen Stub erstellen, der als Konstruktorargument übergeben wird. Dann können Sie diese Kette von Scheinobjekten unterbrechen.

Benutzer-Avatar
silbefreit

PHPUnit wurde entwickelt, um den Konstruktor für mockierte Objekte aufzurufen; Um dies zu verhindern, sollten Sie entweder:

  1. Fügen Sie ein Scheinobjekt als Abhängigkeit in das Objekt ein, bei dem Sie Probleme haben, sich zu verspotten
  2. Erstellen Sie eine Testklasse, die die Klasse erweitert, die Sie aufzurufen versuchen, und die den übergeordneten Konstruktor nicht aufruft

1353890cookie-checkphpunit vermeidet Konstruktorargumente für mock

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy