Skip to main content

Why use mocks

When writing tests, there are operations you don’t actually want to run: sending mail, reading and writing to the cache, calling external APIs, and so on. Replacing these operations with a “fake that pretends to be the real thing” is called mocking. The benefits of using mocks include:
  • Fast tests — Tests finish quickly because external services and heavy operations aren’t executed
  • Stable tests — Tests always produce the same results, unaffected by the state of external services
  • Clear test scope — You can verify a single class or method in isolation
Laravel provides helpers that let you mock events, jobs, facades, and more out of the box. Internally it uses Mockery, which you can use without complex setup.

Mocking objects

To mock an object that is injected via the service container, bind the mock instance into the container. The container will then use the mock instance instead of creating the object.

The mock() method

Laravel’s test case base class provides a mock() method that lets you write the same thing more concisely.

The partialMock() method

When you want to mock only some methods of an object, use partialMock(). Methods that aren’t mocked are executed as usual.

The spy() method

Spies are similar to mocks, but interactions are verified after the code has run. While a mock declares “this method should be called” in advance, a spy checks “was this method called?” afterward.

Mocking facades

Unlike ordinary static method calls, facades can be mocked. They have the same testability as dependency injection while offering a concise syntax. As an example, consider a controller that uses the cache.
To mock the get method of the Cache facade, use expects().
Do not mock the Request facade. Instead, pass input to HTTP test methods like get and post. Similarly, instead of mocking the Config facade, call Config::set() in your test.

Facade spies

To watch a facade with a spy, call the spy() method on the corresponding facade. Spies are convenient when you want to verify interactions after the code has run.

Manipulating time

When testing time-dependent logic, it’s helpful to change what now() or Carbon::now() returns. Laravel’s feature test base class provides helpers for manipulating time.

travel() — move through time

Time travel with closures

If you pass a closure to a time-travel method, time is frozen at the specified moment while the closure runs, and returns to the original time after it completes.

freezeTime() — stop time

freezeTime() freezes the current time. freezeSecond() freezes time at the beginning of the current second.

Practical example: locking inactive threads

Time manipulation is helpful for testing features like a forum where posts get locked after a period of inactivity.
Time manipulation methods like travel() are only available in feature tests (classes that extend Tests\TestCase). They are not available on PHPUnit’s base TestCase.

Method reference

Mocking

Time manipulation

Last modified on July 13, 2026