Mocking Symfony2's request and session in PHPUnit

mocking, phpunit, service, symfony

Solution

Not all code is worth unit testing. Usually this is an indicator that your code could be simplified. When you unit test code that is somewhat complex the tests can become a burden and normally it would be better to do an integration of edge-to-edge test in these cases. It's also not clear in your example how your class gets the `RequestStack` so I will assume that it has been injected in `__construct`.

With that said here's how you would test that code:

protected function setUp()
{
    $this->requestStack = $this->getMock('Fully-qualified RequestStack namespace');

    $this->SUT = new MyClass($this->requestStack);
}    

/** @test */
public function it_should_store_value_in_the_session()
{
    $value = 'test value';

    $request = $this->getMock('Request');
    $request->request = $this->getMock('ParameterBag');
    $session = $this->getMock('Session');

    $this->requestStack
        ->expects($this->atLeastOnce())
        ->method('getCurrentRequest')
        ->will($this->returnValue());

    $request->request
        ->expects($this->atLeastOnce())
        ->method('get')
        ->with('something')
        ->will($this->returnValue($value));

    $request
        ->expects($this->once())
        ->method('getSession')
        ->will($this->returnValue($session));

    $session
        ->expects($this->once())
        ->method('set')
        ->with('somevar', $value);

    $this->SUT->doSomething();
}

This should give you a starting point but beware having a wall-of mocks in your tests because very small changes to the implementation details can cause your tests to fail even though the behaviour is still correct and this is something you want to avoid as much as possible so the tests aren't expensive to maintain.

Edit: I thought some more about your question and realized that typically you can inject the Session as a dependency. If that's possible in your use case it would simplify the tests a lot.

Problem

I have a class that requires the `Symfony2` service `@request_stack` which returns an instance of `Symfony\Component\HttpFoundation\RequestStack`. I use it to retrieve POST and GET values. And also my class uses `Symfony\Component\HttpFoundation\Session` from `Request->getSession()` which it calls to get the current session. Right now my class has a method that looks something like this: ``` class MyClass { public function doSomething() { //Get request from request stack. $Request = $this->RequestStack->getCurrentRequest(); //Get a variable from request $var = $Request->request->get('something'); //Processes $var into $someprocessedvar and lets say it's equal to 3. //Set value to session. $this->Request->getSession()->set('somevar', $someprocessedvar); } } ``` I need to be able to: - Mock `RequestStack`. - Get `Request` from `RequestStack` - Get `Session` from `Reques`t; With all that said how can I test that `MyClass` successfully set the expected value in the session?

Original source