Search code examples
phptestinglaravelbddphpspec

How use class interfaces when using PHPSpec


When testing with PHPSpec how can I use class interfaces injected into my methods rather then the actual concrete class?

For example I have a Product class that injects a VariationInterface into a method:

/**
 * ...
 */
public function addVarient(VarientInterface $varient)
{
    return $this->varients->add($varient);
}

Although since PHPSpec has no IOC container to bind VarientInterface to Varient I cant really test my classes.

Is it not best practice to code to an interface and not a concrete class?


Solution

  • You can mock concrete classes and intefaces in PHPSpec.

    Please verify this example:

    <?php
    
    //file spec/YourNameSpace/ProductSpec.php
    
    namespace spec\YourNameSpace\Product;
    
    use YourNameSpace\VarientInterface;
    use PhpSpec\ObjectBehavior;
    
    class ProductSpec extends ObjectBehavior
    {
        function it_is_varients_container(VarientInterface $varient)
        {
            $this->addVarient($varient);
    
            $this->getVarients()->shouldBe([$varient]);
        }
    }
    

    You just pass VarientInterface as parameter to test method. This VarientInterface is mocked underneath by PhpSpec (really by Prophecy).

    Please check offical phpspec documentaion about mocking http://www.phpspec.net/docs/introduction.html#prophet-objects