مقاله

shouldReceive، Mockery::on، partial mock، overload و تمیزکاری — فراتر از mock ساده facade.

Mockery عمیق در Laravel — mock، spy، partial و expectation پیشرفته

Mockery عمیق در Laravel — mock، spy، partial و expectation پیشرفته

Laravel facade را با Facade::fake() راحت mock می‌کنید؛ برای کلاس خودتان Mockery استاندارد PHP است. سطح مقدماتی در Unit test mock بود — اینجا expectation دقیق و mockهای شکننده را درست می‌کنیم.

ساخت mock و expectation

$gateway = Mockery::mock(PaymentGateway::class);
$gateway->shouldReceive('charge')
    ->once()
    ->with(10000, 'order-1')
    ->andReturn(['ref' => 'abc']);

$result = $gateway->charge(10000, 'order-1');

Argument matcher

->with(Mockery::type('int'), Mockery::pattern('/^order-/'))
->with(Mockery::on(fn ($order) => $order->id > 0))
->withArgs(function ($amount, $id) { return $amount > 0; })

وقتی مقدار دقیق مهم نیست — object پیچیده.

ترتیب و تعداد

->once() | ->twice() | ->times(3) | ->never()
->ordered()  // ترتیب فراخوانی
->andReturn(1, 2, 3)  // sequential

Exception از mock

->andThrow(new PaymentFailedException('declined'));

Spy — فراخوانی واقعی + assert

$spy = Mockery::spy(LogService::class);
$spy->shouldHaveReceived('info')->once()->with('order placed');

برای verify side effect بدون جایگزینی کامل.

Partial mock

$service = Mockery::mock(PostService::class)->makePartial();
$service->shouldReceive('sendNotification')->once();
$service->publish($post);  // بقیه متدها واقعی

فقط یک متد fake — بقیه integration. با احتیاط — coupling.

mock در constructor Laravel

$this->instance(PostRepositoryInterface::class, $mock);
$action = app(CreatePostAction::class);

container swap — تست Action.

Mockery::close()

Pest/PHPUnit معمولاً در tearDown صدا می‌زند. اگر expectation برآورده نشود test fail — «leaked mock».

anti-patterns

  • mock کردن class تحت تست
  • shouldReceive روی همه متدها بدون دلیل
  • assert روی ترتیب داخلی private
  • overload mock برای static — fragile

جایگزین: fake Laravel

Mail::fake()، Http::fake() — نگه‌داری شده تیم. Test doubles.

جمع‌بندی

Mockery برای boundary interface — نه هر کلاس. Dataset: Pest dataset. Coverage: CI.

unit test setup