Search code examples
phpunit-testingphpspec

phpspec scalar value in let


I am trying to use the let function with scalar values. My problem is that the price is an Double, i expected an int 5.

function let(Buyable $buyable, $price, $discount)
{
    $buyable->getPrice()->willReturn($price);
    $this->beConstructedWith($buyable, $discount);
}

function it_returns_the_same_price_if_discount_is_zero($price = 5, $discount = 0) {
    $this->getDiscountPrice()->shouldReturn(5);
}

the error:

✘ it returns the same price if discount is zero
expected [integer:5], but got [obj:Double\stdClass\P14]

is there a way to inject the 5 using the let function?


Solution

  • In PhpSpec, whatever comes in an argument to let(), letgo() or it_*() methods is a test double. It's not meant to be used with scalars.

    PhpSpec uses reflection to get the type from a type hint or a @param annotation. It then creates a fake object with prophecy and injects it into a method. If it can't find a type, it will create a fake of \stdClass. Double\stdClass\P14 has nothing to do with double type. It is a test double.

    Your spec could look like:

    private $price = 5;
    
    function let(Buyable $buyable)
    {
        $buyable->getPrice()->willReturn($this->price);
    
        $this->beConstructedWith($buyable, 0);
    }
    
    function it_returns_the_same_price_if_discount_is_zero() 
    {
        $this->getDiscountPrice()->shouldReturn($this->price);
    }
    

    Although I'd prefer to include everything related to the current example:

    function let(Buyable $buyable)
    {
        // default construction, for examples that don't care how the object is created
        $this->beConstructedWith($buyable, 0);
    }
    
    function it_returns_the_same_price_if_discount_is_zero(Buyable $buyable) 
    {
        // this is repeated to indicate it's important for the example
        $this->beConstructedWith($buyable, 0);
    
        $buyable->getPrice()->willReturn(5);
    
        $this->getDiscountPrice()->shouldReturn(5);
    }