Pertanyaan phpunit menghindari argumen konstruktor untuk mengejek


Apa cara untuk menghindari phpunit harus memanggil konstruktor untuk objek tiruan? Kalau tidak, saya akan membutuhkan objek tiruan sebagai argumen konstruktor, yang lain untuk itu, dll. Api tampaknya seperti ini:

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

Saya tidak membuatnya bekerja. Masih mengeluh tentang argumen konstruktor, bahkan dengan $callOriginalConstructor disetel ke false.

Saya hanya memiliki satu objek dalam konstruktor dan itu adalah suntikan ketergantungan. Jadi saya tidak berpikir saya punya masalah desain di sana.


76
2017-11-10 23:00


asal


Jawaban:


Kamu dapat memakai getMockBuilder bukan hanya getMock:

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

Lihat bagiannya "Uji Ganda" di Dokumentasi PHPUnit untuk detailnya.

Meskipun Anda dapat melakukan ini, lebih baik tidak perlu melakukannya. Anda dapat mem-refactor kode Anda, bukan kelas konkret (dengan konstruktor) yang perlu disuntikkan, Anda hanya bergantung pada antarmuka. Ini berarti Anda dapat mengolok-olok atau stub antarmuka tanpa harus memberitahu PHPUnit untuk memodifikasi perilaku konstruktor.


125
2018-06-08 10:11



Di sini Anda pergi:

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

40
2018-03-09 22:38



Sebagai tambahan, saya ingin melampirkan expects() panggilan ke objek mengejek saya dan kemudian memanggil konstruktor. Dalam PHPUnit 3.7.14, objek yang dikembalikan saat Anda menelepon disableOriginalConstructor() secara harfiah merupakan objek.

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

Sayangnya, di PHP 5.4 ada opsi baru yang tidak mereka gunakan:

ReflectionClass :: newInstanceWithoutConstructor

Karena ini tidak tersedia, saya harus secara manual mencerminkan kelas dan kemudian memanggil konstruktor.

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

Perhatikan, jika functionCallFromConstruct aku s protected, Anda harus menggunakan secara khusus setMethods() sehingga metode yang dilindungi diejek. Contoh:

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

setMethods() harus dipanggil sebelum expect() panggilan. Secara pribadi, saya rantai ini setelah disableOriginalConstructor() tapi sebelum getMock().


3
2018-03-08 02:21



Mungkin Anda perlu membuat rintisan untuk meneruskan sebagai argumen konstruktor. Maka Anda dapat mematahkan rantai objek tiruan itu.


1
2017-12-01 22:30



Atau Anda bisa menambahkan parameter ke getMock untuk mencegah pemanggilan konstruktor default.

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

Namun, saya pikir jawaban dari dave1010 terlihat lebih baik, ini hanya demi kelengkapan.


1
2017-07-21 07:37



PHPUnit dirancang untuk memanggil konstruktor pada objek yang diejek; untuk mencegah hal ini Anda harus:

  1. Menyuntikkan objek tiruan sebagai ketergantungan ke objek yang Anda mengalami kesulitan mengejek
  2. Buat kelas tes yang memperluas kelas yang Anda coba panggil yang tidak memanggil konstruktor induk

0
2017-12-08 21:08