PHPUnit menyediakan beberapa fitur hebat untuk membuat objek tiruan. Idenya adalah ketika Anda menguji kode yang bergantung pada kelas lain, Anda memberikan objek tersebut contoh tiruan dari kelas tersebut, bukan objek nyata. Dengan cara ini Anda memastikan bahwa pengujian Anda hanya akan gagal jika sistem yang diuji rusak, bukan jika salah satu dependensinya rusak. Anda cukup menulis kelas tiruan dan membuat instance-nya, tetapi PHPUnit dapat membuatnya untuk Anda.
Dokumentasi PHPUnit tidak secara eksplisit menyatakan hal ini, tetapi Anda juga dapat membuat objek tiruan dari antarmuka. Jika Anda memikirkannya, itu masuk akal. Dalam banyak kasus, Anda harus benar-benar menggunakan antarmuka tiruan dalam pengujian Anda daripada meniru kelas tertentu. Bagaimanapun, antarmuka adalah kontrak dimana suatu kelas setuju untuk berbicara dengan dunia luar.
sebuah contoh sederhana
Mari kita tulis beberapa kode dengan gaya TDD yang sebenarnya. Katakanlah kita ingin memposting ke Twitter setiap kali seseorang menyetor uang ke rekening bank kita. Kami tidak ingin menguji pengiriman tweet yang sebenarnya. Faktanya, kami belum memikirkan seperti apa kategori Twitter kami nantinya. Inilah pengujian kami:
class BankAccountTest extends PHPUnit_Framework_TestCase
{
public function testSendEmailWhenReceivingMoney()
{
$twitter = $this->getMock('Twitter');
$account = new BankAccount($twitter);
$account->deposit(10);
}
}
Eksekusi pengujian ini gagal karena kami belum memiliki kelas BankAccount.
PHP Fatal error: Class 'BankAccount' not found
Mari kita tambahkan:
class BankAccount
{
private $twitter;
public function __construct(Twitter $twitter)
{
$this->twitter = $twitter;
}
public function deposit($amount){
}
}
Sekarang pengujian berhasil karena alasan sederhana yaitu kami tidak benar-benar menguji apa pun. Mari kita pastikan bahwa BankAccount::deposit() benar-benar mengirimkan tweet. Kita melakukan ini dengan memberitahu mock untuk mengharapkan metode tweet()-nya dipanggil.
class BankAccountTest extends PHPUnit_Framework_TestCase
{
public function testSendEmailWhenReceivingMoney()
{
$twitter = $this->getMock('Twitter');
$twitter->expects($this->once())
->method('tweet');
$account = new BankAccount($twitter);
$account->deposit(10);
}
}
Tes gagal dengan pesan berikut:
1) BankAccountTest::testSendEmailWhenReceivingMoney
Expectation failed for method name is equal to
when invoked 1 time(s)
Method was expected to be called 1 times, actually called 0 times.
Mari tambahkan beberapa kode yang memanggil tweet() ke metode Deposit() kita.
class BankAccount
{
// ...
public function deposit($amount)
{
$this->twitter->tweet("Yay, someone deposited $amount");
}
}
Kami menerima kesalahan baru:
PHP Fatal error:
Call to undefined method Mock_Twitter_28053312::tweet()
Mock_Twitter_28053312 adalah kelas yang dihasilkan oleh PHPUnit berdasarkan antarmuka Twitter, yang belum kami tulis. Kabar baiknya adalah sejauh ini kami telah menemukan seperti apa tampilan antarmukanya:
interface Twitter
{
function tweet($message);
}
sebagai kesimpulan
Inti dari teknik ini adalah kita sekarang telah menulis BankAccount dan tidak perlu khawatir tentang bagaimana penerapan Twitter akan bekerja. Seiring berjalannya waktu, kami menemukan bahwa kami memerlukan implementasi antarmuka Twitter, dan kami menemukan seperti apa tampilan antarmuka tersebut.
Nantinya, kami mungkin membangun implementasi RESTfulTwitter pada Twitter yang menggunakan REST API Twitter untuk mengirim pesan. Jika kita membangun implementasi Twitter terlebih dahulu, kita mungkin ingin menambahkan berbagai fitur yang menurut kita mungkin diperlukan. Sebaliknya, kita menemukan apa yang sebenarnya kita butuhkan. Pengujian kami membuktikan bahwa kode kami mengikuti YAGNI.
Lanjutkan membaca: Antarmuka yang Masuk Akal – 24 September 2013