Dalam PHPUnit, bagaimana untuk mengejek fungsi yang bukan sebahagian daripada kelas?
P粉216807924
P粉216807924 2023-10-29 15:44:54
0
2
711

Projek yang sedang saya kerjakan mengandungi gabungan kod PHP berorientasikan objek dan prosedur. Jadi saya mempunyai sesuatu seperti ini:

function doStuff($value)
{
    $x = $value + 1;

    return $x;
}

class MyClass
{
    private $field;

    public function setMyValue($amount)
    {
        $this->field = doStuff($amount) + doStuff(2 * $amount);
    }
}

Terdapat beberapa kebergantungan ini, tetapi sangat sedikit (anda boleh mengiranya dengan satu tangan). Walau bagaimanapun, saya perlu menulis ujian unit untuk kelas (menggunakan PHPUnit) dan saya tidak tahu cara mengejek fungsi dari terminal (dalam kes ini doStuff). Setahu saya, fungsi mengejek dalam PHPUnit hanya berfungsi dengan kelas.

Saya akan melakukannya tanpa sebarang ejekan, tetapi masalahnya ialah beberapa fungsi ini melakukan beberapa operasi IO;

Bagaimana saya boleh menyelesaikan masalah ini?

P粉216807924
P粉216807924

membalas semua(2)
P粉275883973

Satu-satunya pilihan yang saya lihat ialah suntikan pergantungan kerana kelas anda mahu menggunakan sumber di luar kelas. Jadi ini melanggar beberapa peraturan enkapsulasi.

Bagaimana saya melakukan ini pada masa lalu ialah meletakkan fungsi ini dalam kelas mereka sendiri dan memerlukan/menyertakannya, dan apabila menetapkan pembolehubah ujian, sertakan fail asas dengan fungsi separuh "olok-olok" yang sama yang Mengembalikan keadaan yang diketahui .

Pendekatan saya yang lain ialah mencipta kelas UTILITI ringkas yang mengandungi semua fungsi data ini dan kemudian menggunakan suntikan kebergantungan dan mengejek untuk mengujinya.

class Utilities
{

    function doStuff($value)
    {
        $x = $value + 1;
        return $x;
    }
}

class MyClass
{
    private $UtilitiesObject;

    private $field;

    public function setMyValue($amount)
    {
//        $this->field = doStuff($amount) + doStuff(2 * $amount);
        $this->field = $this->UtilitiesObject->doStuff($amount) + $this->UtilitiesObject->doStuff(2 * $amount);
    }
}

    // Constructor Injection, pass the Utilities object here
    public function __construct($Utilities = NULL)
    {
        if(! is_null($Utilities) )
        {
            if($Utilities instanceof Utilities)
            {
                $this->SetUtilities($Utilities);
            }
        }
    }

    function SetUtilities(Utilities $Utilities)
    {
        $this->UtilitiesObject = $Utilities
    }

}

Ujian:

class UtilitiesTest extends PHPUnit_Framework_TestCase
{

    // Could also use dataProvider to send different returnValues, and then check with Asserts.
    public function testSetMyValue()
    {
        // Create a mock for the Utilities class,
        // only mock the doStuff() method.
        $MockUtilities = $this->getMock('Utilities', array('doStuff'));

        // Set up the expectation for the doStuff() method 
        $MockUtilities->expects($this->any())
                    ->method('doStuff')
                    ->will($this->returnValue(1));

        // Create Test Object - Pass our Mock as the Utilities
        $TestClass = new MyClass($MockUtilities);
        // Or
        // $TestClass = new MyClass();
        // $TestClass->SetUtilitiess($MockUtilities);

        // Test doStuff
        $amount = 10;   // Could be checked with the Mock functions
        $this->assertEquals(2, $TestClass->doStuff($amount));       // Mock always returns 1, so 1+1=2
    }
}
P粉155832941

Anda boleh memanfaatkan dasar sandaran ruang nama PHP apabila anda memanggil fungsi dari ruang nama (ditakrifkan dalam ruang nama global) dan sentiasa memanggilnya fungsi tidak layak.

Ini membolehkan anda membuat olok-olok dengan menyediakan fungsi dalam ruang nama pemanggil.

Untuk menjadikan hidup anda lebih mudah, saya membungkusnya ke dalam perpustakaan php-mock- phpunit yang boleh digunakan dengan PHPUnit:

namespace foo;

use phpmock\phpunit\PHPMock;

class BuiltinTest extends \PHPUnit_Framework_TestCase
{

    use PHPMock;

    public function testTime()
    {
        $time = $this->getFunctionMock(__NAMESPACE__, "time");
        $time->expects($this->once())->willReturn(3);

        $this->assertEquals(3, time());
    }
}
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan