Injeksi ketergantungan tiruan otomatis untuk pengujian
injected Trait
memungkinkan Anda dengan mudah membuat kelas dengan semua dependensinya diejek untuk tujuan pengujian.
Pola berikut ini sangat umum:
A
dengan dependensinya (objek layanan) yang diteruskan melalui konstruktorA
, dengan menyatakan bahwa mereka dipanggil seperti yang diharapkan. Banyak logika pengujian yang akhirnya menjadi boilerplate untuk membangun sebuah objek. injected Trait
bertujuan untuk menghapus boilerplate ini sepenuhnya, sehingga Anda dapat fokus pada hal yang penting: pengujian itu sendiri.
Gunakan composer
untuk mendapatkan rilis terbaru (Anda mungkin hanya memerlukannya untuk pengembangan):
$ composer require sellerlabs/ injected --dev
Misalkan kita sedang mengembangkan aplikasi web, dan kita ingin mengirim email kepada pengguna saat mereka mendaftar. Sebagai contoh sederhana, anggap saja pengguna ditentukan sepenuhnya berdasarkan alamat emailnya. Saat mereka mendaftar, tentu saja kami ingin mengirimi mereka email terima kasih. Selain itu, kami ingin menguji apakah email tersebut benar-benar terkirim tanpa benar-benar mengirimkannya .
Pertama, mari kita definisikan layanan email:
class EmailService
{
public function email ( $ address , $ content )
{
// Send an email to $address with body $content
}
}
(Dalam aplikasi nyata, email
akan mengirimkan email -- kami tidak peduli dengan penerapannya di sini!)
Mari kita definisikan juga UserController
yang menangani proses pendaftaran yang sangat sederhana:
class UserController
{
private $ service ;
public function __construct ( EmailService $ service )
{
$ this -> service = $ service ;
}
public function signUp ( $ emailAddress )
{
$ this -> service -> email ( $ emailAddress , ' Thanks for signing up! ' );
return $ emailAddress ;
}
}
Di sini, kami menyediakan ketergantungan EmailService
melalui konstruktor, dan menggunakannya selama proses pendaftaran (yang sangat sederhana).
Untuk menguji kelas ini, kita harus melakukan salah satu dari dua hal berikut:
EmailService
menggunakan sesuatu seperti Mockery
dan pastikan email
dipanggil dengan argumen yang diharapkan. injected Trait
memungkinkan Anda mencapai opsi 2 tanpa rasa sakit. Mari kita lihat:
use SellerLabs injected injected Trait ;
/**
* Class injected Example
*
* // 1. These are helpful annotations for IDEs and language tools
* @property MockInterface $service
* @method UserController make()
*
* @author Benjamin Kovach <[email protected]>
*/
class injected Example extends PHPUnit_Framework_TestCase
{
// 2. Use our trait
use injected Trait;
// 3. Provide the name of the class to test
protected $ className = UserController::class;
public function testSignUp ()
{
// 4. Make a controller with mocked dependencies
$ controller = $ this -> make ();
$ address = ' [email protected] ' ;
// 5. We can access any mocked dependency of the class as a property
$ this -> service -> shouldReceive ( ' email ' )
-> withArgs (
[
$ address ,
' Thanks for signing up! '
]
);
$ result = $ controller -> signUp ( $ address );
$ this -> assertEquals ( $ address , $ result );
}
}
Setiap kelas yang menggunakan injected Trait
diharuskan memiliki properti $className
, yang digunakan untuk menemukan lokasi kelas yang sedang diuji. injected Trait
menyediakan satu metode publik, make
, yang membuat objek bertipe ini, tetapi mengolok-olok dependensinya dan menyimpannya sebagai properti untuk kelas pengujian itu sendiri.
Jadi, di testSignUp
, kita membuat pengontrol menggunakan make()
, yang memberi kita akses ke objek tipe EmailService
tiruan yang disebut $service
. Ini karena hal ini didefinisikan seperti itu di konstruktor UserController
:
public function __construct ( EmailService $ service )
{
$ this -> service = $ service ;
}
Selama masa uji kasus, variabel anggota $service
terikat pada EmailService
tiruan ini, yang memungkinkan kita membuat ekspektasi tentang apa yang terjadi dengannya ketika metode signUp
pada pengontrol dipanggil. Kami menggunakan Mockery
untuk membuat objek tiruan. Ada beberapa anotasi di komentar kelas, yang membantu pelengkapan otomatis IDE untuk kelas-kelas ini karena properti tiruan dideklarasikan secara dinamis.
Contoh ini ada di tests/ injected Example.php
. Jangan ragu untuk melihat-lihat!
Dampak dari sifat ini mungkin tampak relatif kecil, namun ketika bekerja pada aplikasi besar yang kelasnya memiliki beberapa dependensi, hal ini membuat pengujian menjadi lebih mudah.