子目录中的 CakePHP 运行 会导致 shell 中的 URL、Web 和单元测试出现问题?

CakePHP running in subdirectory creates problems with URLs in shell, web and unit-tests?

我正在使用 CakePHP 2.9.7 并正在尝试编写一个 shell,它应该发送带有 links (Router::url()) 的邮件。 link 将指向我的 CakePHP 应用程序中的一个页面,该页面将使用另一个 link 发送另一封邮件。因此,我们从 shell 发送了一封邮件,从应用程序内部发送了一封邮件。

文档建议我设置 App.fullBaseUrl 如果我想在 shell 中使用路由:https://book.cakephp.org/2.0/en/console-and-shells.html#routing-in-shells-cli。因为我不确定这是否包含完整的基本路径,所以我只是询问并了解到它确实包含在内。所以我确实将 App.fullBaseUrl 设置为 http://example.com/my_app 之类的东西。 shell 中发送的邮件现在非常有效! 但是,其他一些 links,例如从应用程序内部发送的邮件中的那些现在已损坏,因为它们指向 http://example.com/my_app/my_app。我认为这与我想要那些 link 的完整 URL 有关。大多数其他 link 工作正常,因为我不要求完整的 URL。但是,如果我在 HtmlLinkHelper 中传递 'full_base' => true 选项,则会出现同样的问题。

我发现了这个:https://github.com/cakephp/cakephp/pull/1718 所以我猜这会解决我的痛苦,我只是将 App.fullBaseUrl 设置为 http://example.com 并将 App.base 设置为 /myapp。这在两种用法中都很有效。 'Yay' 我想 运行 所有的单元测试。他们不再工作了。

我的单元测试广泛使用 $this->testAction()(在 ControllerTests 中),所有 $this->testAction 调用现在都已损坏。 例如:我的 CartController 中有一个只能通过 GET 调用的索引操作,因此我们编写了一个测试以通过 POST 调用它。这一直有效,直到我设置 'App.base'.

public function testIndexPost() {
    $this->testAction(
        array(
            'controller' => 'Cart',
            'action' => 'index',
        ),
        array(
            'method' => 'POST',
            'return' => 'vars',
        )
    );
}

现在我得到一个错误:

Failed asserting that exception of type "MissingActionException" matches expected exception "MethodNotAllowedException". Message was: "Action CartController::Cart() could not be found.".

堆栈跟踪:

Action CartController::Cart() could not be found.
Test case: CartControllerTest(testIndexPost)

Stack trace:
F:\dev\xampp\htdocs\my_app\vendor\cakephp\cakephp\lib\Cake\Routing\Dispatcher.php : 193
F:\dev\xampp\htdocs\my_app\vendor\cakephp\cakephp\lib\Cake\Routing\Dispatcher.php : 167
F:\dev\xampp\htdocs\my_app\vendor\cakephp\cakephp\lib\Cake\TestSuite\ControllerTestCase.php : 287
ControllerTestCase::_testAction
F:\dev\xampp\htdocs\my_app\vendor\cakephp\cakephp\lib\Cake\TestSuite\ControllerTestCase.php : 199
F:\dev\xampp\htdocs\my_app\app\Test\Case\Controller\CartControllerTest.php : 83
F:\dev\xampp\htdocs\my_app\app\Test\Case\Controller\CartControllerTest.php : 83
CartControllerTest::testIndexPost
F:\dev\xampp\htdocs\my_app\vendor\phpunit\phpunit\PHPUnit\Framework\TestCase.php : 988
F:\dev\xampp\htdocs\my_app\vendor\phpunit\phpunit\PHPUnit\Framework\TestCase.php : 838
F:\dev\xampp\htdocs\my_app\vendor\phpunit\phpunit\PHPUnit\Framework\TestResult.php : 648
F:\dev\xampp\htdocs\my_app\vendor\phpunit\phpunit\PHPUnit\Framework\TestCase.php : 783
F:\dev\xampp\htdocs\my_app\vendor\cakephp\cakephp\lib\Cake\TestSuite\CakeTestCase.php : 82
F:\dev\xampp\htdocs\my_app\vendor\phpunit\phpunit\PHPUnit\Framework\TestSuite.php : 779
F:\dev\xampp\htdocs\my_app\vendor\phpunit\phpunit\PHPUnit\Framework\TestSuite.php : 749
F:\dev\xampp\htdocs\my_app\vendor\phpunit\phpunit\PHPUnit\TextUI\TestRunner.php : 350
F:\dev\xampp\htdocs\my_app\vendor\cakephp\cakephp\lib\Cake\TestSuite\CakeTestRunner.php : 62
F:\dev\xampp\htdocs\my_app\vendor\cakephp\cakephp\lib\Cake\TestSuite\CakeTestSuiteCommand.php : 98
F:\dev\xampp\htdocs\my_app\vendor\cakephp\cakephp\lib\Cake\TestSuite\CakeTestSuiteDispatcher.php : 259
F:\dev\xampp\htdocs\my_app\vendor\cakephp\cakephp\lib\Cake\TestSuite\CakeTestSuiteDispatcher.php : 96
F:\dev\xampp\htdocs\my_app\vendor\cakephp\cakephp\lib\Cake\TestSuite\CakeTestSuiteDispatcher.php : 113
F:\dev\xampp\htdocs\my_app\webroot\test.php : 104

我当然可以设置 'base' => false(这使它再次工作),但感觉不对。我不应该仅仅因为我在我的应用程序中设置了 App.base 就改变了我所有的测试,对吧?

因此,无论我做什么,我都无法让此路由与所有 CLI、Web 和单元测试一起使用。其中之一总是搞砸了。

我是不是做错了什么?
有没有更好的方法来处理这些事情?
这是一个错误吗?

问题似乎是在请求对象中,基本路径没有从为您的 testAction() 调用生成的 URL 中删除。

ControllerTestCase::_testAction() 中,当将 URL 传递给请求对象的构造函数时,可能的基本路径不会像请求对象生成 [=34] 时那样从中删除=] 本身在 CakeRequest::_url() 中,而不是 URL 被设置为原样,这会导致匹配错误的路由。

我建议 report this as a bugControllerTestCase::_testAction() 应该填充 $_SERVER['REQUEST_URI'] 而不是将 URL 传递给CakeRequest 模拟。

在解决此问题之前,尝试像这样暂时修改 ControllerTestCase::_testAction()

$_SERVER['REQUEST_URI'] = $url;
$request = $this->getMock('CakeRequest', array('_readInput'));

https://github.com/cakephp/.../blob/2.9.7/lib/Cake/TestSuite/ControllerTestCase.php#L251