Unit testing CUrlManager impossible!

I’ve tried for days now to find a way to unit test my URL rules.

When you run unit tests within Yii, there’s already a request being made, so working with $_SERVER[‘REQUEST_URI’] doesn’t help.

CUrlManager->parseUrl takes a CHTTPRequest as the parameter, and there is no way to create a new CHTTPRequest and set a URL yourself in that request.

How are we supposed to unit test our custom URL rules for the CUrlManager? Or am I mistaken if I assume that should be possible? I know it’s not the largest part of an application, but the URL rules can indeed become quite complex and having unit tests for them would certainly help in my case.

Personally I test them using selenium. I’m following the fat model pattern so I write unit tests only for models and some components. Controllers, views and configuration options including routes are tested using automated functional tests. They are fast enough to be played multiple times during future implementation. Not as fast as unit tests though…

My solution to test generated routes

  1. Create a helper method



  public function createUrl($route,$params=array()) {

    $url = explode('phpunit',Yii::app()->createUrl($route,$params));

    return $url[1];

  }



take a look at http://www.yiiframework.com/wiki/147/functional-tests-independing-from-your-urlmanager-settings/ for explanation.

  1. Create the tests



  /** @test */

  public function shouldCreateCorrectRoutes() {

    $this->assertEquals('/', $this->createUrl('pages/home'));

    $this->assertEquals('/about', $this->createUrl('pages/about'));

    $this->assertEquals('/contact', $this->createUrl('pages/contact'));

    $this->assertEquals('/help', $this->createUrl('pages/help'));

    $this->assertEquals('/signup', $this->createUrl('users/new'));

    $this->assertEquals('/signin', $this->createUrl('users/login'));

  }



Functional tests in Yii without Selenium can be done with a help of Goutte (requires php 5.3) to simulate browser. It’s faster than Selenium, suitable to create non-ajax web tests.

Example test




  /** @test */

  public function shouldHaveTheRightLinksOnTheLayout() {

    $client = new Client();

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

    $this->assertStringEndsWith('Home', $crawler->filter('title')->text());


    $crawler = $client->click($crawler->selectLink('About')->link());

    $this->assertStringEndsWith('About', $crawler->filter('title')->text());


    $crawler = $client->click($crawler->selectLink('Contact')->link());

    $this->assertStringEndsWith('Contact', $crawler->filter('title')->text());


    $crawler = $client->click($crawler->selectLink('Home')->link());

    $this->assertStringEndsWith('Home', $crawler->filter('title')->text());


    $crawler = $client->click($crawler->selectLink('Sign up now!')->link());

    $this->assertStringEndsWith('Sign up', $crawler->filter('title')->text());

  }



more on that at my github repo