console-helpers/prophecy-phpunit
PHPUnit integration helpers for Prophecy, providing convenience traits and utilities to streamline mock creation, prophecy assertions, and cleanup in your test suite. Designed to reduce boilerplate and keep Prophecy-based unit tests tidy and consistent.
Installation Add the package via Composer:
composer require --dev console-helpers/prophecy-phpunit
No additional configuration is required—it integrates seamlessly with PHPUnit and Prophecy.
First Use Case Replace PHPUnit’s native mocking with Prophecy in a test:
use ConsoleHelpers\Prophecy\ProphecyTestCase;
class ExampleTest extends ProphecyTestCase
{
public function testMockingWithProphecy()
{
$mock = $this->prophesize('App\Services\ExampleService');
$mock->doSomething()->willReturn('mocked result');
$result = $mock->reveal()->doSomething();
$this->assertEquals('mocked result', $result);
}
}
Key Files to Explore
ProphecyTestCase.php: Core test case class extending PHPUnit’s TestCase.Test Case Inheritance
Extend ProphecyTestCase instead of PHPUnit’s base TestCase:
class UserServiceTest extends ProphecyTestCase { ... }
prophesize() method.Mocking Dependencies Replace manual mocks with Prophecy’s fluent syntax:
$repository = $this->prophesize('App\Repositories\UserRepository');
$repository->find(1)->willReturn((new User())->setName('Test User'));
Partial Mocks
Use partialMock() for existing objects (if needed, though Prophecy discourages this):
$service = $this->partialMock('App\Services\RealService', ['log']);
Laravel-Specific Patterns
$this->app->instance('App\Contracts\UserRepository', $this->prophesize('App\Repositories\UserRepository')->reveal());
$events = $this->prophesize('Illuminate\Events\Dispatcher');
$this->app->instance('events', $events->reveal());
Assertion Helpers Combine with PHPUnit assertions:
$mock->methodWasCalled('save');
$this->assertTrue($mock->methodWasCalled('save'));
reveal() Timing
reveal() before invoking methods on a prophecy.
$mock->doSomething(); // Fails: Prophecy object not revealed.
$mock->reveal()->doSomething();
Double Invocation
Prophecy\Exception\DoubleInvocationException if a method is called more times than defined.
$mock->save()->willReturn(true); // Only allows 1 call.
$mock->save(); // OK
$mock->save(); // Throws exception.
willReturnOnConsecutiveCalls() or willReturnCallback().Laravel Facade Mocking
Auth::shouldReceive()) may not work as expected.$this->app->instance('auth', $this->prophesize('Illuminate\Auth\AuthManager')->reveal());
Static Method Mocking
partialMock() or a wrapper class.Enable Prophecy Debugging
Set the PROPHECY_DEBUG environment variable to 1 for detailed error messages:
PROPHECY_DEBUG=1 phpunit
Inspect Prophecies
Use getProphecy() to debug interactions:
$prophecy = $mock->getProphecy();
$prophecy->checkPredictions(); // Verify all expectations were met.
Laravel’s Service Provider Mocking
setUp():
public function setUp(): void
{
parent::setUp();
$this->app->instance('App\Contracts\ExampleContract', $this->prophesize('App\Services\ExampleService')->reveal());
}
Custom Prophecy Classes
Extend ProphecyTestCase to add domain-specific helpers:
class ApiTestCase extends ProphecyTestCase
{
protected function createMockApiClient(): \GuzzleHttp\Client
{
return $this->prophesize('GuzzleHttp\Client')->reveal();
}
}
Trait for Shared Mocks Use traits to avoid repetition:
trait MocksUsers
{
protected function createMockUserRepository(): \App\Repositories\UserRepository
{
return $this->prophesize('App\Repositories\UserRepository')->reveal();
}
}
Integration with Laravel’s MockApplication
Combine with Laravel’s testing tools for deeper integration:
use Illuminate\Foundation\Testing\Concerns\InteractsWithContainer;
class ServiceTest extends ProphecyTestCase
{
use InteractsWithContainer;
// ...
}
How can I help you explore Laravel packages today?