【发布时间】:2011-07-15 08:30:48
【问题描述】:
我有一个 Zend Framework 控制器的单元测试扩展 Zend_Test_PHPUnit_ControllerTestCase。
测试正在调度一个动作,该动作转发给另一个动作,如下所示:
// AdminControllerTest.php
public testAdminAction()
$this->dispath('/admin/index/index');
// forwards to login page
$this->assertModule('user');
$this->assertController('profile');
$this->assertController('login');
$this->assertResponseCode(401);
}
// NewsControllerTest.php
public testIndexAction()
{
$this->dispatch('/news/index/index');
$this->assertModule('news');
$this->assertController('index');
$this->assertController('index');
$this->assertResponseCode(200);
}
当它们作为单独的测试运行时,这两个测试都通过了。
当我在同一个测试套件中运行它们时,第二个失败了。
而是调度 /news/index/index 之前的请求被调度(用户模块)。
如何追踪这个错误?看起来我在应用程序的某个地方有一些全局状态,但我无法调试它。如何在套件中的测试之间转储对象? setUpBefore/AfterClass 是静态的,所以没有太多关于对象实例的数据。
我知道这是一种猜猜看的问题。在这里很难提供可靠的数据,因为它们会占据很多地方,所以请随时询问详细信息。
整个单元测试设置或多或少类似于:Testing Zend Framework MVC Applications - phly, boy, phly 或 Testing Zend Framework Controllers « Federico Cargnelutti。
解决办法:
我已经确定了这个问题(小睡片刻之后)。问题不在于单元测试设置,而在于测试代码。
我根据模块名称使用不同的 ACL 对象。使用哪一个由静态调用操作助手确定,该助手将结果缓存在私有静态变量中以加快处理速度。仅当在测试套件中运行时才执行此缓存。我只需要对这段代码进行更多的单元测试:)
(对于这样的垃圾帖子,我很抱歉,但我已经坚持了一天,我希望其他人在一般的单元测试中经历过类似的这种 Heisenbug)
【问题讨论】:
-
我不知道这是否有帮助,但是当您单独运行它们时,您可能正在为每个单独的测试运行 setUp() 并且在测试套件中您有一个 setUp() 方法在所有测试发生之前可能只运行一次。我不熟悉您使用的技术,但只是指出可能的一般问题来源。祝你好运!
-
我假设您使用的是 Zend 的
ControllerTestCase。您可以在测试用例及其调用的内容中发布您的引导代码吗?您是否在使用自己的基础测试用例,它是 CTC 的子类,以及测试用例的子类? -
测试干扰是一个常见的头痛问题,必须根据具体情况加以解决。对于我们的项目,我创建了
SetupActions,并注册了TestListener实现,该实现执行全局setUp和tearDown操作以在每次测试后重置静态状态。我们在难以追踪哪些测试最终设置这些状态并且重置它们的成本非常低的情况下使用它们。
标签: unit-testing zend-framework phpunit integration-testing