我正试图使用codeception为控制器函数编写一个API测试用例,但我遇到了一个问题,即到控制器函数的路由似乎没有得到正确评估,评估似乎因我的测试用例中的内容而异。
下面是我的测试用例中的一个代码示例:
use 'ApiTester;
class CustomerRegisterCest
{
// tests
public function testGetRegister(ApiTester $I)
{
$I->sendGET('register');
$I->seeResponseCodeIs(200);
}
public function testPostRegister(ApiTester $I)
{
$I->sendPOST('register', [
// set the data in here
]);
$I->seeResponseCodeIs(200);
}
我有一个routes.php文件,其中包含以下路由:
Route::get('/', ['as' => 'home', 'uses' => 'HomeController@getIndex']);
Route::get('register', ['as' => 'getRegister', 'uses' =>'RegistrationController@getRegister']);
Route::post('register', ['as' => 'postRegister', 'uses' => 'RegistrationController@postRegister']);
我在我的控制器类中插入了一些调试语句,这样我就可以看到运行的路由,比如:
Log::debug('GET register'); // or GET index or POST register, etc
目前,我已经从控制器类中剥离了所有内容,以便只包含调试语句。
当我如上所述运行测试用例时,我得到以下调试输出:
GET register
GET index
因此,sendPOST('register',…)实际上路由到"/"的GET路由,而不是"/register"的POST路由。在测试用例之外,一切都正常工作——我可以POST到寄存器路由很好,路由似乎工作正常,问题只出现在代码感知测试用例中。
如果我更改测试用例,以便在同一个函数调用中执行sendGET和sendPOST,例如:
// tests
public function testPostRegister(ApiTester $I)
{
$I->sendGET('register');
$I->seeResponseCodeIs(200);
$I->sendPOST('register', [
// set the data in here
]);
$I->seeResponseCodeIs(200);
}
然后我看到这个调试输出:
GET register
GET register
因此,通过将sendGET插入到与sendPOST相同的函数中,它已经改变了sendPOST行为,因此它现在路由到用于注册的GET路由,而不是用于索引的GET路由(但仍然不会路由到正确的POST路由)。
我试过打开xdebug,但从xdebug输出中也没有任何关于发生了什么的线索。
我想我在经过大量命令行调试(使用phpstorm)后找到了答案:
控制器中的POST寄存器路由处理功能声明如下:
public function postRegister(RegistrationRequest $request)
{
需要通过依赖项注入传入Request的实例。该请求包含一些验证代码,如果由于某种原因验证代码无法完成(例如抛出异常),则永远不会调用控制器函数,因为构建请求失败。
在浏览器领域,这会引发500错误,但在代码感知领域,异常会被不同地捕获,并返回重定向到/没有数据。这一切都发生在控制器函数之外,而不是内部,因此控制器函数中的Log语句永远不会运行,因为函数永远不会被调用。codeception中的异常处理程序是一个通用陷阱。
隐含的建议是,控制器中的依赖注入可能是个坏主意。或者,通用异常处理程序可能是个坏主意。