مقاله

Mockery، fake dependencies، تست PostService و Action — سریع و focused بدون HTTP.

Unit Test و Mock در Laravel — تست Service بدون دیتابیس

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.

quality pipeline