jager91
jager91

Reputation: 282

Test controller action by phpunit, symfony

I need to test my controller action and i need advice. It's how my controller looks:

class SampleController extends Controller
{    
    public function sampleAction(Request $request)
    {
        $lang = 'en';

        return $this->render('movie.html.twig', [
            'icons' => $this->container->getParameter('icons'),
            'language' => $lang,
            'extraServiceUrl' => $this->getAccount()->getExtraServiceUrl(),
            'websiteUrl' => $this->getAccount()->getWebsiteUrl(),
            'myProfileUrl' => $this->getAccount()->getMyProfileUrl(),
            'redirectForAnonUser' => $this->container->get('router')->generate('login'),
            'containerId' => $request->getSession()->get("_website"),
            'isRestricted' => $this->getLicense()->isRestricted(),
            'isPremiumAvaible' => $this->getLicense()->isPremiumAvaible()
        ]);
    }

    private function getAccount()
    {
        return $this->container->get('context')->getAccount();
    }

    private function getLicense()
    {
        return $this->container->get('license');
    }
}

And now, normally I test controllers by behat, but this one just render twig and set variables in so I probably can't test it by behat. I tried to test it by phpUnit and it can work, but what is the best way to mock chain methods? Or maybe you have other way to test it? btw container is private so I need reflection? Greetings

Upvotes: 7

Views: 10599

Answers (1)

Maksym  Moskvychev
Maksym Moskvychev

Reputation: 1674

There are 2 approaches to test Controllers:

  1. Functional tests. You test whole application together - from fetching data from db to rendering response in Symfony core. You can use fixtures to set-up test data.
  2. Unit test. You test only this method, all dependencies are mocked.

Unit tests are good in testing services with just few dependencies. But for controllers Functional tests are better in most cases.

Functional test with session mocking in you case could look like:

namespace Tests\AppBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;

class PostControllerTest extends WebTestCase
{
    public function testYourAction()
    {
        $client = static::createClient();

        $user = null;//todo: load user for test from DB here

        /** @var Session $session */
        $session = $client->getContainer()->get('session');

        $firewall = 'main';
        $token = new UsernamePasswordToken($user, null, $firewall, $user->getRoles());
        $session->set('_security_'.$firewall, serialize($token));
        $session->save();

        $cookie = new Cookie($session->getName(), $session->getId());
            $this->client->getCookieJar()->set($cookie);

        $crawler = $client->request('GET', '/your_url');

        $response = $this->client->getResponse();
        $this->assertEquals(200, $response->getStatusCode());

        //todo: do other assertions. For example, check that some string is present in response, etc..
    }
}

Upvotes: 9

Related Questions