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
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.get method of the Cache facade, use expects().
Facade spies
To watch a facade with a spy, call thespy() 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 whatnow() 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.