如何在phpspec测试中使用laravel会话

如何在phpspec测试中使用laravel会话

问题描述:

I'm trying to test a very simple class with phpspec.

Some methods of the class that should be tested

/**
 * @param Store $session
 */
function __construct(Store $session)
{
    $this->session = $session;
}

/**
 * @param Store $session
 */
function __construct(Store $session)
{
    $this->session = $session;
}

/**
 * Set the current order id
 *
 * @param $orderId
 */
public function setCurrentOrderId($orderId)
{
    $this->session->set($this->sessionVariableName, $orderId);

    return $this;
}

/**
 * Get the current order id
 *
 * @return mixed
 */
public function getCurrentOrderId()
{
    return $this->session->get($this->sessionVariableName);
}

and a piece of the test

use Illuminate\Session\Store;


class CheckoutSpec extends ObjectBehavior
{
    function let(Store $session)
    {
        $this->beConstructedWith($session);
    }

    function it_is_initializable()
    {
        $this->shouldHaveType('Spatie\Checkout\Checkout');
    }

    function it_stores_an_orderId()
    {
        $this->setCurrentOrderId('testvalue');

        $this->getCurrentOrderId()->shouldReturn('testvalue');

    }
}

Unfortunately the test fails on it_stores_an_orderId with this error expected "testvalue", but got null.

When the methods setCurrentOrderId and getCurrentOrderId are used in artisan's tinker they work just fine.

It seems that in my test environment there something wrong with the setup of the session.

How can this problem be solved?

You're actually trying to test more than just your class. PHPSpec specs (and unit tests in general) are meant to be run in isolation.

What you really want in this case is to make sure that your class works as intended, isn't it? Simply mock the Store class and only check that the necessary methods from it are being called and mock their return results if there are any. This way you'll still know that your class works as intended and won't test something that has been thoroughly tested already.

Here's how you might do it:

function it_stores_an_orderId(Store $session)
{
    $store->set('testvalue')->shouldBeCalled();
    $store->get('testvalue')->shouldBeCalled()->willReturn('testvalue');

    $this->setCurrentOrderId('testvalue');
    $this->getCurrentOrderId()->shouldReturn('testvalue');

}

If you still want to involve some of the other classes directly, something like Codeception or PHPUnit might be more appropriate, since you can control your testing environment more.

However, if you still want to do this with PHPSpec, it might be possible with this package (I haven't tried it myself though, so no guarantee).