【问题标题】:Testing redirections CakePHP 2.0测试重定向 CakePHP 2.0
【发布时间】:2012-04-30 20:15:42
【问题描述】:

我一直在看食谱上的一些例子,但我不明白: http://book.cakephp.org/2.0/en/development/testing.html#a-more-complex-example

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

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);        
}

【问题讨论】:

  • 我想知道它是否抛出了一个空视图错误。在这种情况下,您可以尝试在控制器上模拟 render 函数,因为无论如何都没有删除视图。
  • 嘲笑它是什么意思?是的,没有,重定向工作正常,视图操作不为空。
  • Mocking 是一个测试过程,你可以让某些方法返回你想要的结果。例如,CakeRequest::send() 被嘲笑并被告知什么也不做,因此它不发送标头。您甚至可以告诉模拟方法期望什么或如何响应(请参阅:phpunit.de/manual/3.0/en/mock-objects.html)。要使用 Cake 轻松模拟,请查看:book.cakephp.org/2.0/en/development/…ControllerTestCase::testAction() 会自动为您完成其中的一些操作。
  • 我一直在尝试,但我没有得到它的工作。做这样的事情不是更简单吗? stackoverflow.com/questions/1986907/…
  • 这可能会显着改变代码的行为。我会在一分钟内整理出一个正确的答案。

标签: unit-testing cakephp testing redirect cakephp-2.0


【解决方案1】:

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

// 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 上的 send() 方法和整个 SessionComponent。

有关模拟的更多信息:http://www.phpunit.de/manual/3.0/en/mock-objects.html

有关generate()的更多信息:http://book.cakephp.org/2.0/en/development/testing.html#using-mocks-with-testaction

【讨论】:

  • 调用后:$this->testAction('/posts/delete/1');什么都不执行。所以我什至不能做 $results = $this->headers['Location'];重定向会阻止它。
  • 听起来好像发生了其他事情。尝试发布完整的测试用例,在 delete() 操作中分散一些调试语句,使用另一个使用重定向的操作进行检查,等等。
【解决方案2】:

您可能遇到错误,因为 $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');
    }

【讨论】:

    【解决方案3】:

    永远不会打印回声,您的“删除”函数总是在结束前调用重定向。

    【讨论】:

      【解决方案4】:
      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));        
      }
      

      }

      普莱尼克斯, 这不是完全错误的吗? 您正在删除评论并将评论的 id 传递给帖子的视图控制器?那么,您是在查看帖子或评论吗?还有什么建议吗?

      【讨论】:

        猜你喜欢
        • 2013-12-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-06-05
        • 2012-04-22
        相关资源
        最近更新 更多