我正在关注Mark Story的“Testing CakePHP controllers - Mock Objects edition”来测试一些具有重定向的控制器操作。我目前正在简单测试中模拟redirect()方法。我想重构一些代码,如下所示:
if (!$this->Model->someGuardCondition($id)){
$this->redirect($this->referer());
}
if ($this->Model->save($this->data)){
$this->redirect(array('controller' => 'controllerName', 'action' => 'actionName', $id));
}
问题是,如果第一个条件为真,那么我不希望测试执行第二个条件,因为这是它在生产中的工作方式。有没有办法在调用redirect()时终止测试而不会杀死整个测试套件?我知道我可以在每次重定向后放置一个return语句,但我宁愿不修改代码只是为了让测试行为正确。我应该坚持使用一堆丑陋的嵌套if / else语句吗?
编辑20120215 我将尝试使我的示例代码更完整,以证明问题:
some_controller.php:
class SomeController extends AppController
function some_action($id) {
if (!$this->Model->hasAuthorityToDoThis($id)){
$this->Session->setFlash(__('The id is invalid for some reason'));
$this->redirect($this->referer());
}
if ($this->Model->save($this->data)){
$this->Session->setFlash(__('Save successful'));
$this->redirect(array('controller' => 'controllerName', 'action' => 'actionName', $id));
}
}
}
some_controller_test.php:
class SomeControllerTestCase extends AppCakeTestCase {
function testSomeAction() {
$this->SomeController->Session = new MockSessionComponent();
$this->SomeController->Session->expectOnce('setFlash');
$this->SomeController->some_action('some-invalid-id'); // Note this is an invalid ID.
}
}
因此,您可以从上面看到,我正在使用无效ID测试操作。这意味着第一个条件将通过。它会将flash消息设置为“由于某种原因id无效”并重定向到referer。在CakePHP重定向将调用重定向时退出脚本,因此代码永远不会实际进入模型 - > save()。但是,如果我在测试中模拟出redirect(),那么该方法基本上只返回而没有任何效果,并且控制器继续运行超过它应该的点。这很好,因为它不会中止测试套件,但它很糟糕,因为它实际上并不反映实际代码的行为。
说保存$ this->数据的调用很好。然后第一和第二条件都将通过。这将导致测试失败,因为您应该只设置一次Flash消息。
我猜测没有办法轻松编写这样的代码,只需坚持使用嵌套的if / else块就更好了。我只是想减少圈复杂度。
答案 0 :(得分:0)
嵌套测试:
while (!$complete) {
if (!$this->Model->someGuardCondition($id)){
$this->redirect($this->referer());
$complete = 1;
continue;
}
if ($this->Model->save($this->data)){
$this->redirect(array('controller' => 'controllerName', 'action' => 'actionName', $id));
$complete = 1;
continue;
}
}
或者您可以使用if else语句:
if (!$this->Model->someGuardCondition($id)){
$this->redirect($this->referer());
} elseif($this->Model->save($this->data)){
$this->redirect(array('controller' => 'controllerName', 'action' => 'actionName', $id));
} else {
return;
}
将每个测试移动到不同的方法,以便可以单独调用它们。
答案 1 :(得分:0)
只需使用return:
$this->redirect($this->referer());
return;
这样,您的控制器操作将在重定向后结束,与复杂的if/else
等相比,它的代码更改要少得多。