PHPSpec: Mocking methods of the object being tested

PHPSpec is very opinionated and won’t let you mock anything of an object being tested. It helps you write better code. This, however, causes issues when you are writing specs for legacy code which (usually) was not well designed.

There is a way you can get around this limitation – a child class. Let’s say the class you want to test is called “Car” and it has a method called “getNumberOfDoors” that you need to mock. Just write a child class and mock the method in it. Here is the code:


// Car.php
class Car
{
    // We want to test this method
    public function isSportsCar()
    {
        return $this->getNumberOfDoors() <= 3;
    }

    // It would make life much easier if we can mock this method
    // to test isSportsCar() method above
    public function getNumberOfDoors()
    {
        return 4;
    }
}

// CarSpec.php

// ..namespace and use statements here .. 

class CarSpec extends ObjectBehavior
{
    public function let()
    {
        $this->beADoubleOf('CarSpy');
    }

    public function it_can_identify_car_type()
    {
        // And viola! we can test to our heart's content for all possible
        // edge cases

        $this->setNumberOfDoors(2);
        $this->isSportsCar()->shouldReturn(true);
    }
}

// The child class which we can use to manipulate the actual class
// we want to test
class CarSpy extends Car
{
    protected $numDoors;

    public function getNumberOfDoors()
    {
       return $this->numDoors;
    }

    public function setNumberOfDoors($val)
    {
        $this->numDoors = $val;
    }
}


Posted

in

by

Comments

2 responses to “PHPSpec: Mocking methods of the object being tested”

  1. Mark Armstrong Avatar
    Mark Armstrong

    Shouldn’t this line:
    $this->getNumberOfDoors()->shouldReturn(true);

    Be this:
    $this->isSportsCar()->shouldReturn(true);

  2. Moazzam Avatar

    Yes, it should! Thanks for pointing it out. I corrected it in the article.

Leave a Reply

Your email address will not be published. Required fields are marked *