Mix Prophecy Mock Framework with PHPUnit Mock Builder to Create Mocks for Not Existing Classes and Magic Methods

Submitted by Peter Majmesku on Wed, 08/16/2017 - 12:20
Testing

Prophecy is great as long as you are creating mocks for classes or methods, which are existing in your code base. The benefit is, that the usage is a bit more convenient compared with the PHPUnit mock builder (e.g. method definition and parameter handling). Therefor Prophecy is integrated into PHPUnit by default.

If you want to create mocks for classes, which are not existing in your code base or if you want to mock magic methods, this will become a problem. You could create a real class, just to have the class/method. But this is not an nice solution. That's why mixing mocking functionality from the Prophecy mocking framework and the PHPUnit mocking framework makes sense.

Here I am not questioning, if it is good to create tests for classes, that do not belong to your code base. I am just showing a way to handle this.

The following example works with PHPUnit 4.8.35 and up. The Prophecy mocking framework is part of PHPUnit.

// Mock the object via Prophecy - generally more convenient than with PHPUnit itself
$entityManager $this->prophesize(EntityManager::class);

// Create the mock object by PHPUnit, for a class that does not exist.
$shippingMethodRepository $this->getMockBuilder('ShippingMethod')
    ->
disableOriginalClone()
    ->
setMethods(['findByName'])
    ->
getMock();

// Set the not existing method.
$shippingMethodRepository->method('findByName')
    ->
willReturn(['Spedition''Hermes']);

// Define that getRepository() can retrieve any arguments and get a "real" object to test with.
$entityManager->getRepository(Prophecy\Argument::any())
    ->
willReturn($shippingMethodRepository);

// Mock a few methods with Prophecy as you like
$entityManager->persist(Prophecy\Argument::any())->willReturn(null);
$entityManager->flush(Prophecy\Argument::any())->willReturn(null);

// Get the mocked object, which will fake behavior
$entityManager->reveal();

// Will return 'Hermes'
end($entityManager->getRepository('AppBundle:ShippingMethod')->findByName('Delivery')); 

Add new comment

Restricted HTML

  • Allowed HTML tags: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.