CakePHP控制器单元测试

时间:2014-12-09 21:43:59

标签: unit-testing cakephp cakephp-2.0

我想测试控制器方法的添加动作。我想验证保存操作的结果。所以基本上我想发一个帖子到动作,并在请求完成后使用查找验证我的测试中的结果。 $ this-> testAction()似乎不是正确的方法(请参阅下面的代码中的注释)。该怎么做?

控制器代码类似于:

Public function add() {
  .....
  if ($this->request->is('post') && isset($this->request->data['InvoiceEntry'])) {
    ....
    $this->request->data = $this->__someMethod($this->request->data);
    if ($this->Invoice->saveAssociated($this->request->data)) {
      ....
      $this->redirect(array('action' => 'index'));
    }
  .....
}

测试代码:

public function testAdd() {
   $data = array('Invoice' => array(...), 'InvoiceEntry' => array(....));

    // Method 1
    $this->testAction('/invoices/add/', array(
        'method' => 'post',
        'data' => $data,
    ));
    // Unable to do find after testAction because testAction basically is the test?


    // Method 2:
    $this->controller = $this->generate('Invoices');
    $_SERVER['REQUEST_METHOD'] = 'POST';
    $this->controller->requestAction('/invoices/add',array(
        'data' => $data
    ));
   // not working because requestAction() follows the redirect in the add method
}

2 个答案:

答案 0 :(得分:1)

您应该可以在testAction之后执行任何操作。它不是测试本身,只是在操作中运行代码。 如果您在Model::find()后执行testAction会怎样?甚至是debug('foo');exit;?这应该执行。

顺便说一句,在您的控制器中,您应该在重定向前使用return。它是由CakePHP推荐的,因为你的终端不是浏览器(我假设你用命令行测试,而不是webroot/test.php,如果你停止并使用终端作为通过浏览器测试可能会导致不一致的测试,因为的cookie /会话)并且不会遵循重定向,因此将执行可能在Controller::redirect()之后的代码,并且您不希望这样:)

答案 1 :(得分:1)

首先,您应该在测试的setUp()方法中初始化Model类:

public function setUp() {
    parent::setUp();
    $this->Invoice = ClassRegistry::init('Invoice');
}

之后你可以像其他人一样使用那个模型。所以在你这样做之后:

$this->testAction('/invoices/add/', array(
    'method' => 'post',
    'data' => $data,
));

然后,您应该能够检查是否已添加,例如:

/*
 * Check if the last insert id is 13
 * (NOTE: This actual number depends on how your fixture looks.)
 */
$this->assertEquals(13, $this->Invoice->getLastInsertID());

或查看一些内容,例如:

// Find the latest invoice
$invoice = $this->Invoice->find('first', array(
    'order' => array('id' => 'desc')
));

/*
 * Verify the data matches your $data array
 * e.g. if the customer_id of this invoice is 1
 * (this depends on what is actually in $data)
 */
$this->assertEquals(1, $invoice['Invoice']['customer_id']);

最后,不要忘记在tearDown()方法中破坏Model实例:

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