> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Mocking

> Mock objects, facades, spies, and time manipulation for testing Laravel applications

## Introduction

When testing Laravel applications, you may wish to "mock" certain aspects of your application so they are not actually executed during a given test. For example, when testing a controller that dispatches an event, you may wish to mock the event listeners so they are not actually executed during the test. This allows you to only test the controller's HTTP response without worrying about the execution of the event listeners since the event listeners can be tested in their own test case.

Laravel provides helpful methods for mocking events, jobs, and other facades out of the box. These helpers primarily provide a convenience layer over Mockery so you do not have to manually make complicated Mockery method calls.

## Mocking objects

When mocking an object that is going to be injected into your application via Laravel's [service container](/en/service-container), you will need to bind your mocked instance into the container as an `instance` binding. This will instruct the container to use your mocked instance of the object instead of constructing the object itself:

<CodeGroup>
  ```php Pest theme={null}
  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');
          })
      );
  });
  ```

  ```php PHPUnit theme={null}
  use App\Service;
  use Mockery;
  use Mockery\MockInterface;

  public function test_something_can_be_mocked(): void
  {
      $this->instance(
          Service::class,
          Mockery::mock(Service::class, function (MockInterface $mock) {
              $mock->expects('process');
          })
      );
  }
  ```
</CodeGroup>

### The `mock()` method

You may use the `mock` method provided by Laravel's base test case class to make this more convenient. The following example is equivalent to the example above:

```php theme={null}
use App\Service;
use Mockery\MockInterface;

$mock = $this->mock(Service::class, function (MockInterface $mock) {
    $mock->expects('process');
});
```

### The `partialMock()` method

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:

```php theme={null}
use App\Service;
use Mockery\MockInterface;

$mock = $this->partialMock(Service::class, function (MockInterface $mock) {
    $mock->expects('process');
});
```

### The `spy()` method

If you want to [spy](http://docs.mockery.io/en/latest/reference/spies.html) on an object, Laravel's base test case class offers a `spy` method as a convenient wrapper around the `Mockery::spy` method. Spies are similar to mocks; however, spies record any interaction between the spy and the code being tested, allowing you to make assertions after the code is executed:

```php theme={null}
use App\Service;

$spy = $this->spy(Service::class);

// ...

$spy->shouldHaveReceived('process');
```

<Info>
  The key difference between a mock and a spy: a **mock** defines expectations before the code runs and verifies them automatically, while a **spy** records interactions so you can assert after the code runs.
</Info>

## Mocking facades

Unlike traditional static method calls, [facades](/en/facades) (including real-time facades) may be mocked. This provides a great advantage over traditional static methods and grants you the same testability that you would have if you were using traditional dependency injection.

For example, consider the following controller action:

```php theme={null}
<?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 [
            // ...
        ];
    }
}
```

We can mock the call to the `Cache` facade by using the `expects` method, which returns an instance of a [Mockery](https://github.com/mockery/mockery) mock. Since facades are actually resolved and managed by the Laravel service container, they have much more testability than a typical static class:

<CodeGroup>
  ```php Pest theme={null}
  <?php

  use Illuminate\Support\Facades\Cache;

  test('get index', function () {
      Cache::expects('get')
          ->with('key')
          ->andReturn('value');

      $response = $this->get('/users');

      // ...
  });
  ```

  ```php PHPUnit theme={null}
  <?php

  namespace Tests\Feature;

  use Illuminate\Support\Facades\Cache;
  use Tests\TestCase;

  class UserControllerTest extends TestCase
  {
      public function test_get_index(): void
      {
          Cache::expects('get')
              ->with('key')
              ->andReturn('value');

          $response = $this->get('/users');

          // ...
      }
  }
  ```
</CodeGroup>

<Warning>
  You should not mock the `Request` facade. Instead, pass the input you desire into the [HTTP testing methods](/en/testing) such as `get` and `post` when running your test. Likewise, instead of mocking the `Config` facade, call the `Config::set` method in your tests.
</Warning>

## Facade spies

If you would like to [spy](http://docs.mockery.io/en/latest/reference/spies.html) on a facade, you may call the `spy` method on the corresponding facade. Spies are similar to mocks; however, spies record any interaction between the spy and the code being tested, allowing you to make assertions after the code is executed:

<CodeGroup>
  ```php Pest theme={null}
  <?php

  use Illuminate\Support\Facades\Cache;

  test('values are stored in cache', function () {
      Cache::spy();

      $response = $this->get('/');

      $response->assertStatus(200);

      Cache::shouldHaveReceived('put')->with('name', 'Taylor', 10);
  });
  ```

  ```php PHPUnit theme={null}
  use Illuminate\Support\Facades\Cache;

  public function test_values_are_stored_in_cache(): void
  {
      Cache::spy();

      $response = $this->get('/');

      $response->assertStatus(200);

      Cache::shouldHaveReceived('put')->with('name', 'Taylor', 10);
  }
  ```
</CodeGroup>

## Interacting with time

When testing, you may occasionally need to modify the time returned by helpers such as `now` or `Illuminate\Support\Carbon::now()`. Thankfully, Laravel's base feature test class includes helpers that allow you to manipulate the current time.

### Traveling through time

<CodeGroup>
  ```php Pest theme={null}
  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();
  });
  ```

  ```php PHPUnit theme={null}
  public function test_time_can_be_manipulated(): void
  {
      // 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();
  }
  ```
</CodeGroup>

### Closures with time travel

You may also provide a closure to the various time travel methods. The closure will be invoked with time frozen at the specified time. Once the closure has executed, time will resume as normal:

```php theme={null}
$this->travel(5)->days(function () {
    // Test something five days into the future...
});

$this->travelTo(now()->subDays(10), function () {
    // Test something during a given moment...
});
```

### Freezing time

The `freezeTime` method may be used to freeze the current time. Similarly, the `freezeSecond` method will freeze the current time but at the start of the current second:

```php theme={null}
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) {
    // ...
});
```

### Practical example: locking inactive forum threads

All of the methods discussed above are primarily useful for testing time sensitive application behavior, such as locking inactive posts on a discussion forum:

<CodeGroup>
  ```php Pest theme={null}
  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();
  });
  ```

  ```php PHPUnit theme={null}
  use App\Models\Thread;

  public function test_forum_threads_lock_after_one_week_of_inactivity(): void
  {
      $thread = Thread::factory()->create();

      $this->travel(1)->week();

      $this->assertTrue($thread->isLockedByInactivity());
  }
  ```
</CodeGroup>

## Method reference

### Mocking

| Method                                 | Description                                         |
| -------------------------------------- | --------------------------------------------------- |
| `$this->mock(Class::class, fn)`        | Create a full mock and bind it in the container     |
| `$this->partialMock(Class::class, fn)` | Mock only specific methods; others execute normally |
| `$this->spy(Class::class)`             | Create a spy and bind it in the container           |
| `$this->instance(Class::class, $mock)` | Bind any mock instance into the container           |
| `Facade::expects('method')`            | Mock a facade method call                           |
| `Facade::spy()`                        | Spy on a facade                                     |
| `$spy->shouldHaveReceived('method')`   | Assert a method was called on a spy                 |

### Time manipulation

| Method                     | Description                                       |
| -------------------------- | ------------------------------------------------- |
| `$this->travel(n)->unit()` | Move time forward or backward by the given amount |
| `$this->travelTo(Carbon)`  | Travel to a specific point in time                |
| `$this->travelBack()`      | Return to the present time                        |
| `$this->freezeTime(fn)`    | Freeze time for the duration of the closure       |
| `$this->freezeSecond(fn)`  | Freeze time at the start of the current second    |
