Apabila menulis ujian unit, cabaran utama ialah memastikan ujian anda memfokus pada kod yang sedang diuji tanpa gangguan daripada sistem luaran atau kebergantungan. Di sinilah objek olok-olok berperanan dalam PHPUnit. Mereka membenarkan anda mensimulasikan kelakuan objek sebenar dengan cara terkawal, menjadikan ujian anda lebih dipercayai dan lebih mudah untuk diselenggara. Dalam artikel ini, kami akan meneroka apakah objek olok-olok, sebab ia berguna dan cara menggunakannya dengan berkesan dalam PHPUnit.
Objek olok-olok ialah versi simulasi objek sebenar digunakan dalam ujian unit. Mereka membenarkan anda untuk:
Olok-olok amat berguna dalam senario berikut:
Apabila bekerja dengan objek olok-olok, anda akan menjumpai dua istilah: mengejek dan mengejek:
PHPUnit memudahkan untuk mencipta dan menggunakan objek olok-olok dengan kaedah createMock(). Di bawah ialah beberapa contoh yang menunjukkan cara bekerja dengan objek olok-olok dengan berkesan.
Dalam contoh ini, kami mencipta objek olok-olok untuk pergantungan kelas dan menentukan kelakuannya.
use PHPUnit\Framework\TestCase; class MyTest extends TestCase { public function testMockExample() { // Create a mock for the SomeClass dependency $mock = $this->createMock(SomeClass::class); // Specify that when the someMethod method is called, it returns 'mocked value' $mock->method('someMethod') ->willReturn('mocked value'); // Pass the mock object to the class under test $unitUnderTest = new ClassUnderTest($mock); // Perform the action and assert that the result matches the expected value $result = $unitUnderTest->performAction(); $this->assertEquals('expected result', $result); } }
Penjelasan:
Kadangkala, anda perlu mengesahkan bahawa kaedah dipanggil dengan parameter yang betul. Begini cara anda boleh melakukannya:
public function testMethodCallVerification() { // Create a mock object $mock = $this->createMock(SomeClass::class); // Expect the someMethod to be called once with 'expected argument' $mock->expects($this->once()) ->method('someMethod') ->with($this->equalTo('expected argument')) ->willReturn('mocked value'); // Pass the mock to the class under test $unitUnderTest = new ClassUnderTest($mock); // Perform an action that calls the mock's method $unitUnderTest->performAction(); }
Isi Penting:
Untuk menunjukkan aplikasi dunia sebenar bagi objek olok-olok, mari kita ambil contoh kelas PaymentProcessor yang bergantung pada antara muka PaymentGateway luaran. Kami ingin menguji kaedah processPayment PaymentProcessor tanpa bergantung pada pelaksanaan sebenar PaymentGateway.
Berikut ialah kelas PaymentProcessor:
class PaymentProcessor { private $gateway; public function __construct(PaymentGateway $gateway) { $this->gateway = $gateway; } public function processPayment(float $amount): bool { return $this->gateway->charge($amount); } }
Kini, kami boleh membuat olok-olok untuk PaymentGateway untuk menguji kaedah processPayment tanpa berinteraksi dengan gerbang pembayaran sebenar.
use PHPUnit\Framework\TestCase; class PaymentProcessorTest extends TestCase { public function testProcessPayment() { // Create a mock object for the PaymentGateway interface $gatewayMock = $this->createMock(PaymentGateway::class); // Define the expected behavior of the mock $gatewayMock->method('charge') ->with(100.0) ->willReturn(true); // Inject the mock into the PaymentProcessor $paymentProcessor = new PaymentProcessor($gatewayMock); // Assert that processPayment returns true $this->assertTrue($paymentProcessor->processPayment(100.0)); } }
Pecahan Ujian:
You can also verify that the charge method is called exactly once when processing a payment:
public function testProcessPaymentCallsCharge() { $gatewayMock = $this->createMock(PaymentGateway::class); // Expect the charge method to be called once with the argument 100.0 $gatewayMock->expects($this->once()) ->method('charge') ->with(100.0) ->willReturn(true); $paymentProcessor = new PaymentProcessor($gatewayMock); $paymentProcessor->processPayment(100.0); }
In this example, expects($this->once()) ensures that the charge method is called exactly once. If the method is not called, or called more than once, the test will fail.
Let’s assume you have a UserService class that depends on a UserRepository to fetch user data. To test UserService in isolation, you can mock the UserRepository.
class UserService { private $repository; public function __construct(UserRepository $repository) { $this->repository = $repository; } public function getUserName($id) { $user = $this->repository->find($id); return $user->name; } }
To test this class, we can mock the repository:
use PHPUnit\Framework\TestCase; class UserServiceTest extends TestCase { public function testGetUserName() { // Create a mock for the UserRepository $mockRepo = $this->createMock(UserRepository::class); // Define that the find method should return a user object with a predefined name $mockRepo->method('find') ->willReturn((object) ['name' => 'John Doe']); // Instantiate the UserService with the mock repository $service = new UserService($mockRepo); // Assert that the getUserName method returns 'John Doe' $this->assertEquals('John Doe', $service->getUserName(1)); } }
Mock objects are invaluable tools for writing unit tests in PHPUnit. They allow you to isolate your code from external dependencies, ensuring that your tests are faster, more reliable, and easier to maintain. Mock objects also help verify interactions between the code under test and its dependencies, ensuring that your code behaves correctly in various scenarios
Atas ialah kandungan terperinci Memahami Objek Olok-olok dalam Pengujian PHPUnit. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!