skeith22's avatar
Level 22

In Depth difference of Mock and Partial Mock in Laravel Testing

Does anyone know what's the big difference of mock and partialMock in testing? I would be great if someone would give like a cases or scenario where one could decide which is the better approach for a certain test

0 likes
2 replies
LaryAI's avatar
Level 58

In Laravel testing, both mock and partialMock are used to create test doubles, but they serve different purposes and are used in different scenarios.

Mock

A mock is a fully simulated object that mimics the behavior of a real object. When you create a mock, you are essentially creating a stand-in for the actual object, and you can specify how it should behave during the test. This is useful when you want to isolate the unit of work you are testing and avoid dependencies on other parts of the system.

Example Scenario for mock

Suppose you have a service that sends emails, and you want to test a method that uses this service without actually sending an email.

public function testEmailIsSent()
{
    $emailService = $this->mock(EmailService::class, function ($mock) {
        $mock->shouldReceive('send')
             ->once()
             ->with('[email protected]', 'Subject', 'Message')
             ->andReturn(true);
    });

    $userService = new UserService($emailService);
    $result = $userService->notifyUser('[email protected]');

    $this->assertTrue($result);
}

In this example, EmailService is mocked, and the send method is expected to be called once with specific parameters. This allows you to test the notifyUser method in isolation.

Partial Mock

A partialMock is a hybrid between a real object and a mock. It allows you to mock certain methods of an object while keeping the rest of the object’s behavior intact. This is useful when you want to test a method in the context of the real object but need to control or simulate the behavior of some methods.

Example Scenario for partialMock

Suppose you have a class with a method that makes an external API call, and you want to test another method that depends on the result of this API call.

public function testProcessData()
{
    $apiService = $this->partialMock(ApiService::class, function ($mock) {
        $mock->shouldReceive('fetchData')
             ->once()
             ->andReturn(['data' => 'mocked data']);
    });

    $result = $apiService->processData();

    $this->assertEquals('processed mocked data', $result);
}

In this example, ApiService is partially mocked. The fetchData method is mocked to return specific data, while the processData method is tested in the context of the real ApiService object.

When to Use Each

  • Use mock when you want to completely isolate the unit of work you are testing from its dependencies. This is useful for unit tests where you want to ensure that the behavior of the unit is independent of other parts of the system.

  • Use partialMock when you need to test a method in the context of the real object but want to control or simulate the behavior of some methods. This is useful for integration tests where you want to test the interaction between methods within the same object.

By understanding the differences and appropriate use cases for mock and partialMock, you can write more effective and focused tests in your Laravel applications.

MohamedTammam's avatar

When mocking a class you pass all method calls to that mock. However, with partialMock only specified methods will be passed to the mock, others will be passed to the original class.

You may use the partialMock method when you only need to mock a few methods of an object. The methods that are not mocked will be executed normally when called

https://laravel.com/docs/11.x/mocking#mocking-objects

#Scenario

Let's say you have a service class that interact with external APIs and modify the database. You want to mock external APIs methods for the sake of testing, however for the methods that modify the database you don't need to mock. In fact you need to test the original behavior of them without mocking.

2 likes

Please or to participate in this conversation.