cakephp 2.6 控制器测试用例在重复的 testAction() 调用中抛出 MissingActionException

cakephp 2.6 controller test case throwing MissingActionException on duplicate testAction()-call

我希望任何人都可以帮助我解决我的测试环境。

我的设置

我正在基于 phpunit 3.7.22 和 cake 版本 2.6.9 实施单元测试。 运行 ubuntu 12.04 LTS 与 PHP 5.4.43-1 和 postgresql 9.1.

我实施了控制器测试模拟蛋糕 Auth 组件以在会话中拥有一个用户,因为我的测试依赖于此。我的控制器 return json 结果,因为它是基于 JS 的前端的 API。我使用生成的控制器的 testAction() 调用来调用我的控制器方法。

<?php
App::uses('RequesttypesController', 'Svc.Controller');

class RequesttypesWithResultControllerTest extends ControllerTestCase
{

    public $fixtures = array(
        'app.requesttype',
        'app.user',
        'app.privilege',
        'app.groupsprivilege',
        'app.groupsuser',
        'app.groupscompany',
        'app.company',
    );

    /**
     * Mock the requesttype object so that it can return results depending on the desired outcome
     * 
     * @see CakeTestCase::setUp()
     */
    public function setUp()
    {
        parent::setUp();    
        $this->controller = $this->generate('Svc.Requesttypes', array(
            'models' => array(
                'Requesttype'
            ),
            'components' => array(
                'Auth' => array(
                    'user'
                ),
                'Session',
                'RequestHandler'
            )
        ));

        $this->controller->Auth->staticExpects($this->any())
        ->method('user')
        ->will($this->returnValue(array(
            'id' => 123,
            'username' => 'myTestUser',
            'company' => 'myTestCompany',
            'usertype_id' => '456',
        ))
        );
        $authResult = $this->controller->Auth->user();
    }

    public function tearDown()
    {
        parent::tearDown();
        unset($this->controller);
    }

    /**
     * A logged in user produces a number of requesttypes
     */
    public function testLoggedInUser()
    {
        $result = $this->testAction('/svc/requesttypes/getMyRequesttypes', array('return' => 'vars'));
        $this->assertNotEmpty($this->vars, 'Did not receive webservice response');
        $this->assertTrue(isset($this->vars['data']['code']), 'Received invalid webservice response');
        $this->assertEqual($this->vars['data']['code'], SvcAppController::RESPONSE_CODE_SUCCESS);
    }

}
?>

本次测试顺利通过。现在我想用不同的设置测试我的控制器操作,例如不同用户类型的用户、来自不同公司的用户等等。如果我现在在 RequesttypesWithResultControllerTest-class 中创建第二个测试方法,调用相同的 testAction-url,我得到一个 MissingActionException 说:

"Action RequesttypesController::() could not be found."

似乎 testAction 调用了一个空的控制器动作,即使动作-url 作为参数传递也是如此。我尝试通过将控制器清零并再次调用 $this->generate() 来重新初始化控制器,但这也无济于事。

当然,我可以通过为每个测试创建一个自己的测试控制器来帮助自己解决问题,这些测试最终会产生一堆重复的测试代码,但这对我来说似乎不合适。

我是不是滥用了测试环境,或者如何解释这个异常?有什么想法吗?

提前感谢分担我的头痛!

经过进一步的代码调试,我们终于找到了错误。我们不小心把/Config/routes.php文件最后一行的require语句改成了require_once 因为在测试环境中抛出了一些 "Class already defined Exceptions"。

错误routes.php:

require_once CAKE . 'Config' . DS . 'routes.php';

对于应用程序本身没有任何区别,因为每个请求只需要初始化一次路由。但是在测试环境中,路由被重新初始化了几次,这在 require_once include 中是不可能的。

这条线应该是这样的,默认情况下是这样的:

正确routes.php:

require CAKE . 'Config' . DS . 'routes.php';