0

在成功遵循 Zend Framework 2 “入门”教程后,我开始了2.1 版的单元测试示例,并且逐字逐句地执行 PHPUnit 失败:

Failed asserting response redirects to "/album", actual redirection is "/album/"

这是文件中的相关代码IndexControllerTest.php

public function testAddActionRedirectsAfterValidPost() {

    $albumTableMock = $this->getMockBuilder('Album\Models\AlbumTable')
                           ->disableOriginalConstructor()
                           ->getMock();

    $albumTableMock->expects($this->once())
                   ->method('saveAlbum')
                   ->will($this->returnValue(null));

    $serviceManager = $this->getApplicationServiceLocator();
    $serviceManager->setAllowOverride(true);
    $serviceManager->setService('Album\Models\AlbumTable', $albumTableMock);

    $postData = array('title' => 'Led Zeppelin III', 'artist' => 'Led Zeppelin');
    $this->dispatch('/album/add', 'POST', $postData);
    $this->assertResponseStatusCode(302);

    $this->assertRedirectTo('/album');
}

这是我在addAction()函数内的内容AlbumController.php

            // Redirect to list of albums
            return $this->redirect()->toRoute('album');

.htaccess文件是 Skeleton Application 附带的文件,并且要彻底,我已经在浏览器中对其进行了测试,http://localhost/zf2-tut/album并且http://localhost/zf2-tut/album/都可以正确解析,并且在添加条目的过程中,它确实将我重定向回带有斜杠。

我知道这可能有点小气,但我想学习解决此类问题的正确方法。

我知道我可以更改断言测试以包含斜杠,但由于示例没有遵循该示例并且 toRoute() 方法没有斜杠,我假设我的代码或环境中可能出现错误在某个地方,我认为让测试偏离它正在测试的内容是不好的做法。

处理这个问题的最佳方法是什么?如果我在某处进行了更改,导致 url 用尾部斜杠解析,我实际上更喜欢在这种情况下,但希望我的代码是干净的,并且不会留下任何歧义,所以我希望有关路线的任何内容都清楚指示尾随斜杠是预期的。

仅供参考,在遵循教程后,我对我的文件夹结构和命名空间做了一些小改动,根据个人喜好将“模型”更改为“模型”。这绝不会影响这个问题(afaik),但我想指出这一点,所以它不是一个红鲱鱼。


编辑:在我发布我的问题后不久,通过更多的工作,我意识到在这种情况下尾斜杠是如何附加到我的路线上的,并将其发布在答案中。但是,根据我的回答,我想了解为什么 Zend Framework 2 在它应该是可选的时附加斜线,以及如何使用 PHPUnit 正确测试它。

4

1 回答 1

0

I guess typing all this out jogged something in my memory as I remembered something odd about the routing config from the tutorial when I went through it several days ago.

Sure enough, in Routing and controllers, the example displayed currently shows:

'router' => array(
    'routes' => array(
        'album' => array(
            'type'    => 'segment',
            'options' => array(
                'route'    => '/album[/][:action][/:id]',
                'constraints' => array(
                    'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
                    'id'     => '[0-9]+',
                ),
                'defaults' => array(
                    'controller' => 'Album\Controller\Album',
                    'action'     => 'index',
                ),
            ),
        ),
    ),
),

Here, the route shows the trailing slash after album encapsulated on it's own, which allows for optional matching. However, the paragraph immediately following the example, plus several comments, make reference to the route previously being /album[/:action][/:id]. The current implementation has the effect of redirecting to the route with a trailing slash. Despite being optional, the controller puts it there so it fails the phpunit test (which judging by the tutorial section's comments, used to be in this portion of the tutorial but now has it's own separate section).

I've verified that changing the route to the older example does indeed redirect without a trailing slash and therefore the phpunit test passes but I then lose my ability to optionally route to this section with a trailing slash. I would prefer to be able to optionally match on this.

So, the "How is this happening?" question has been resolved but I would really like to know how to test for an optional match or if I should just revise the assertion test to check for a trailing slash here. Also, why does Zend\Mvc (or whichever relevant part of the framework, if otherwise) tack on the trailing slash if it's optional?

于 2013-04-11T00:29:27.913 回答