Makale boyunca test süreçleri için en güncel birim testleri kütüphanesi "pest" tercih edilmiştir.
Laravel uygulamalarını test ederken, uygulamanızın belirli yönlerini "taklit etmek" isteyebilirsiniz, böylece bunlar belirli bir test sırasında gerçekten yürütülmez. Örneğin, bir olayı gönderen bir denetleyiciyi test ederken, olay dinleyicilerini taklit etmek isteyebilirsiniz, böylece bunlar test sırasında gerçekten yürütülmez. Bu, olay dinleyicileri kendi test durumlarında test edilebildiğinden, olay dinleyicilerinin yürütülmesi konusunda endişelenmeden yalnızca denetleyicinin HTTP yanıtını test etmenizi sağlar. Laravel, olayları, işleri ve diğer cepheleri kutudan çıktığı gibi taklit etmek için yararlı yöntemler sağlar. Bu yardımcılar, öncelikle Mockery üzerinde bir kolaylık katmanı sağlar, böylece karmaşık Mockery yöntem çağrılarını manuel olarak yapmak zorunda kalmazsınız.
Alaycı Nesneler (Mocking Objects)
Laravel'in servis konteyneri aracılığıyla uygulamanıza enjekte edilecek bir nesneyi mocklarken, mock edilmiş örneğinizi konteynere bir örnek bağlaması olarak bağlamanız gerekecektir. Bu, konteynere nesnenin kendisini oluşturmak yerine mock edilmiş nesne örneğini kullanmasını söyleyecektir:
use App\Service;
use Mockery;
use Mockery\MockInterface;
test('something can be mocked', function () {
$this->instance(
Service::class,
Mockery::mock(Service::class, function (MockInterface $mock) {
$mock->expects('process');
})
);
});Bunu daha kullanışlı hale getirmek için Laravel'in temel test durumu sınıfı tarafından sağlanan mock metodunu kullanabilirsiniz. Örneğin, aşağıdaki örnek yukarıdaki örneğe eşdeğerdir:use App\Service;
use Mockery\MockInterface;
$mock = $this->mock(Service::class, function (MockInterface $mock) {
$mock->expects('process');
});Bir nesnenin yalnızca birkaç metodunu taklit etmeniz gerektiğinde partialMock metodunu kullanabilirsiniz. Taklit edilmeyen metotlar çağrıldığında normal şekilde yürütülecektir:use App\Service;
use Mockery\MockInterface;
$mock = $this->partialMock(Service::class, function (MockInterface $mock) {
$mock->expects('process');
});Benzer şekilde, bir nesneyi gözetlemek istiyorsanız, Laravel'in temel test durumu sınıfı, Mockery::spy yönteminin etrafında kullanışlı bir sarmalayıcı olarak bir casus yöntemi sunar. Casuslar, sahtelere benzer; ancak casuslar, casus ile test edilen kod arasındaki herhangi bir etkileşimi kaydeder ve kod yürütüldükten sonra iddialarda bulunmanıza olanak tanır:use App\Service;
$spy = $this->spy(Service::class);
// ...
$spy->shouldHaveReceived('process');Alaycı Cepheler (Mocking Facades)Geleneksel statik yöntem çağrılarının aksine, cepheler (gerçek zamanlı cepheler dahil) alay konusu edilebilir. Bu, geleneksel statik yöntemlere göre büyük bir avantaj sağlar ve geleneksel bağımlılık enjeksiyonu kullanıyor olsaydınız sahip olacağınız aynı test edilebilirliği size sağlar. Test ederken, genellikle denetleyicilerinizden birinde gerçekleşen bir Laravel cephesine yapılan bir çağrıyı alay konusu yapmak isteyebilirsiniz. Örneğin, aşağıdaki denetleyici eylemini göz önünde bulundurun:
<?php
namespace App\Http\Controllers;
use Illuminate\Support\Facades\Cache;
class UserController extends Controller
{
/**
* Retrieve a list of all users of the application.
*/
public function index(): array
{
$value = Cache::get('key');
return [
// ...
];
}
}Cache cephe çağrısını, bir Mockery mock örneğini döndürecek olan expects metodunu kullanarak mocklayabiliriz. Cepheler aslında Laravel servis konteyneri tarafından çözülüp yönetildiği için, tipik bir statik sınıftan çok daha fazla test edilebilirliğe sahiptirler. Örneğin, Cache cephesi'nin get metoduna yaptığımız çağrıyı mocklayalım:<?php
use Illuminate\Support\Facades\Cache;
test('get index', function () {
Cache::expects('get')
->with('key')
->andReturn('value');
$response = $this->get('/users');
// ...
});Not : Request cephesini taklit etmemelisiniz. Bunun yerine, testinizi çalıştırırken istediğiniz girdiyi get ve post gibi HTTP test yöntemlerine geçirin. Aynı şekilde, Config cephesini taklit etmek yerine, testlerinizde Config::set metodunu çağırın.Cephe Casusları (Facades Spies)
Bir cepheyi gözetlemek isterseniz, ilgili cephedeki casus metodunu çağırabilirsiniz. Casuslar mock'lara benzer; ancak casuslar casus ile test edilen kod arasındaki herhangi bir etkileşimi kaydeder ve kod yürütüldükten sonra iddialarda bulunmanıza olanak tanır:
<?php
use Illuminate\Support\Facades\Cache;
test('values are be stored in cache', function () {
Cache::spy();
$response = $this->get('/');
$response->assertStatus(200);
Cache::shouldHaveReceived('put')->with('name', 'Taylor', 10);
});Test Süreçlerinde Zamanla EtkileşimTest ederken, now veya IlluminateSupportCarbon::now() gibi yardımcılar tarafından döndürülen zamanı ara sıra değiştirmeniz gerekebilir. Neyse ki, Laravel'in temel özellik test sınıfı, geçerli zamanı değiştirmenize izin veren yardımcılar içerir:
test('time can be manipulated', function () {
// Travel into the future...
$this->travel(5)->milliseconds();
$this->travel(5)->seconds();
$this->travel(5)->minutes();
$this->travel(5)->hours();
$this->travel(5)->days();
$this->travel(5)->weeks();
$this->travel(5)->years();
// Travel into the past...
$this->travel(-5)->hours();
// Travel to an explicit time...
$this->travelTo(now()->subHours(6));
// Return back to the present time...
$this->travelBack();
});Çeşitli zaman yolculuğu yöntemlerine bir kapanış da sağlayabilirsiniz. Kapanış, belirtilen zamanda dondurulan zaman ile çağrılacaktır. Kapanış yürütüldüğünde, zaman normal şekilde devam edecektir:$this->travel(5)->days(function () {
// Test something five days into the future...
});
$this->travelTo(now()->subDays(10), function () {
// Test something during a given moment...
});freezeTime yöntemi geçerli zamanı dondurmak için kullanılabilir. Benzer şekilde, freezeSecond yöntemi geçerli zamanı dondurur ancak geçerli saniyenin başlangıcında:use Illuminate\Support\Carbon;
// Freeze time and resume normal time after executing closure...
$this->freezeTime(function (Carbon $time) {
// ...
});
// Freeze time at the current second and resume normal time after executing closure...
$this->freezeSecond(function (Carbon $time) {
// ...
})Beklediğiniz gibi, yukarıda tartışılan yöntemlerin hepsi öncelikle, bir tartışma forumunda etkin olmayan gönderileri kilitlemek gibi zamana duyarlı uygulama davranışlarını test etmek için yararlıdır:use App\Models\Thread;
test('forum threads lock after one week of inactivity', function () {
$thread = Thread::factory()->create();
$this->travel(1)->week();
expect($thread->isLockedByInactivity())->toBeTrue();
});
)