Unit testing 测试重定向CakePHP 2.0

Unit testing 测试重定向CakePHP 2.0,unit-testing,cakephp,testing,redirect,cakephp-2.0,Unit Testing,Cakephp,Testing,Redirect,Cakephp 2.0,我一直在看烹饪书上的一些例子,但我不明白: 如何在这样的删除操作中测试重定向 public function delete($id = null){ $this->Comment->id = $id; if (!$this->Comment->exists()) { throw new NotFoundException(__('Invalid comment')); }

我一直在看烹饪书上的一些例子,但我不明白:

如何在这样的删除操作中测试重定向

public function delete($id = null){         
        $this->Comment->id = $id;
        if (!$this->Comment->exists()) {
            throw new NotFoundException(__('Invalid comment'));
        }
        if ($this->Comment->delete()) {         
            $this->Session->setFlash(__('Comment deleted'));
            return $this->redirect(array('controller' => 'posts', 'action' => 'view', $idPost));
        }
        $this->Session->setFlash(__('Comment was not deleted'));
        return $this->redirect(array('controller' => 'posts', 'action' => 'view', $idPost));        
    }
}
测试在重定向调用后停止,因此它甚至不会打印此回显:

public function testDelete(){       
    $result = $this->testAction("/comments/delete/1");
    echo "this is not printed";
    print_r($this->headers);        
}

永远不会打印回显,函数“delete”总是在结束前调用重定向。

测试删除操作应该与测试任何其他操作相对相同。您的测试用例可能看起来像这样

// notice it extends ControllerTestCase
class PostsControllerTest extends ControllerTestCase {

    function testDelete() {
      $this->testAction('/posts/delete/1');
      $results = $this->headers['Location'];
      // your OP code redirected them to a view, which I assume is wrong
      // because the item would be deleted
      $expected = '/posts/index';
      // check redirect
      $this->assertEquals($results, $expected);

      // check that it was deleted
      $this->Posts->Post->id = 1;
      $this->assertFalse($this->Posts->Post->exists());
    }

}
当然,这只是检查明显的问题。您还可以检查会话并编写预期出现异常的测试。如果它仍然没有到达测试用例的结尾或继续,则会发生其他事情

您可以使用
ControllerTestCase
上的
generate
方法生成简单的模拟

function testDelete() {
  $Posts = $this->generate('Posts', array(
    'components' => array(
      'Email' => array('send'),
      'Session'
    )
  ));
  // set ControllerTestCase to use this mock
  $this->controller = $Posts;

  $this->testAction('/posts/some_action_that_sends_email');
}
上面将首先生成PostsController的模拟,以在测试期间使用。它还模拟EmailComponent和整个SessionComponent上的
send()
方法

有关模拟的详细信息:


有关
generate()
的详细信息:

可能是由于
$idPost
未定义而导致错误

我会这样写:

public function delete($id = null){         
        $this->Comment->id = $id;
        if (!$this->Comment->exists()) {
            throw new NotFoundException(__('Invalid comment'));
        }
        if ($this->Comment->delete()) {         
            $this->Session->setFlash(__('Comment deleted'));
        } else {
            $this->Session->setFlash(__('Comment was not deleted'));
        }
        $this->redirect(array('controller' => 'posts', 'action' => 'view', $id));        
    }
}
public function testDeleteWithSuccess() {
        $Controller = $this->generate('Comments', array(
            'components' => array(
                'Session'
            ),
            'models' => array(
                'Comment' => array('exists')
            )
        ));

        $Controller->Comment->expects($this->once())
            ->method('exists')
            ->will($this->returnValue(true));

        $Controller->Session->expects($this->once())
            ->method('setFlash')
            ->with('Comment deleted');

        $this->testAction("/comments/delete/ID");

        $this->assertEquals($this->headers['Location'], 'http://'. $_SERVER['HTTP_HOST'] . '/posts/view/ID');
    }
然后测试如下:

public function delete($id = null){         
        $this->Comment->id = $id;
        if (!$this->Comment->exists()) {
            throw new NotFoundException(__('Invalid comment'));
        }
        if ($this->Comment->delete()) {         
            $this->Session->setFlash(__('Comment deleted'));
        } else {
            $this->Session->setFlash(__('Comment was not deleted'));
        }
        $this->redirect(array('controller' => 'posts', 'action' => 'view', $id));        
    }
}
public function testDeleteWithSuccess() {
        $Controller = $this->generate('Comments', array(
            'components' => array(
                'Session'
            ),
            'models' => array(
                'Comment' => array('exists')
            )
        ));

        $Controller->Comment->expects($this->once())
            ->method('exists')
            ->will($this->returnValue(true));

        $Controller->Session->expects($this->once())
            ->method('setFlash')
            ->with('Comment deleted');

        $this->testAction("/comments/delete/ID");

        $this->assertEquals($this->headers['Location'], 'http://'. $_SERVER['HTTP_HOST'] . '/posts/view/ID');
    }
}

普莱尼克斯, 这不是完全错了吗?
您正在删除注释并将注释的id传递给帖子的视图控制器?那么,你这样做是在看帖子还是评论??还有其他建议吗?

我想知道它是否抛出了空视图错误。在这种情况下,您可以尝试在控制器上模拟
render
函数,因为没有删除视图。模拟它是什么意思?是的,没有,重定向工作正常,视图操作不是空的。模拟是一个测试过程,你可以让某些方法返回你想要的。例如,
CakeRequest::send()
被模拟,并被告知什么也不做,因此它不发送头。您甚至可以告诉被模拟的方法期望什么或如何响应(请参阅:)。要使用蛋糕轻松进行模拟,请查看:
ControllerTestCase::testAction()
会自动为您执行一些操作。我一直在尝试,但没有成功。这样做不是更简单吗?这可能会显著改变代码的行为。我会在一分钟内给出一个正确的答案。在这个电话之后:$this->testAction('/posts/delete/1');没有执行任何操作。所以我甚至不能做$results=$this->headers['Location'];重定向停止了它。那么听起来好像发生了什么事情。尝试发布完整的测试用例,在
delete()
操作中分散一些调试语句,用另一个使用重定向的操作检查它,等等。