Unit Test و Mock در Laravel — تست Service بدون دیتابیس
Feature test کندتر است — هر کدام HTTP و migration. Unit test منطق Service را با mock repository میزند — میلیثانیه. هدف: اگر قانون تخفیف عوض شد، یک تست کوچک بترکد نه کل suite.
چه چیزی Unit Test شود؟
- PostService::calculateReadingTime
- PriceCalculator
- SlugGenerator
- Pure functions و DTO
نه: routing، blade — آن Feature است — Feature test.
مثال pure
// tests/Unit/ReadingTimeTest.php
it('calculates reading time from word count', function () {
$action = new CalculateReadingTimeAction();
$html = str_repeat('word ', 400);
expect($action->execute($html))->toBe(2);
});
Mock با Mockery
it('creates post via repository', function () {
$repo = Mockery::mock(PostRepository::class);
$repo->shouldReceive('create')
->once()
->with(['title' => 'Test'])
->andReturn(new Post(['title' => 'Test']));
$service = new PostService($repo, app(SlugService::class));
$post = $service->create(['title' => 'Test']);
expect($post->title)->toBe('Test');
});
Laravel container mock
$this->mock(PaymentGateway::class, function ($mock) {
$mock->shouldReceive('charge')->once()->andReturn(['id' => 'pay_123']);
});
fake facade
Http::fake([
'api.example.com/*' => Http::response(['ok' => true], 200),
]);
// service که Http::post میزند
Http::assertSent(fn ($req) => $req->url() === 'https://api.example.com/charge');
partial mock
فقط یک متد — بقیه واقعی. با احتیاط — brittle میشود.
چه زمانی mock نکنیم
over-mock = تست implementation نه behavior. integration سبک گاهی بهتر — یک Feature test.
ترکیب با معماری
interface برای PaymentGateway — mock آسان — معماری لایهای.
جمعبندی
هر Service public method پیچیده → حداقل یک unit. Pest: مقدمه. Event: fake Event.