问题似乎在于 Doctrine 在执行期间缓存了它更新的任何对象。在生产环境中的每个 Web 请求之后,这都会被清除 - 每次执行一个请求 - 但在测试环境中,它似乎在请求之间持续存在,因为它们都发生在同一次执行中。
在测试将新项目添加到列表的过程时变得很麻烦 - 列表在内存中(测试浏览器之前已经访问过它的页面),新项目被创建,保存但它们之间的链接不是在内存中形成。
有针对性地刷新相关对象
如果您知道要强制刷新的对象,您可以:
$SomeDoctrineRecordObject->refreshRelated(); // for all relationships
$SomeDoctrineRecordObject->refreshRelated($relation); // for a specific one
(对于上面的 List 和 Item 示例,你会$list->refreshRelated('item')
)
这仅在您已经使用 Doctrine 对象时才有用,否则每次需要刷新时都必须将其从路由或数据库中拉出。更通用的方法是扩展sfTestFunctional
类并覆盖可能导致关系更改并因此需要触发刷新的方法。
所有对象的一般刷新
清除 Doctrine 对象缓存的代码:
$manager = Doctrine_Manager::getInstance();
$connection = $manager->getCurrentConnection();
$tables = $connection->getTables();
foreach ( $tables as $table ) {
$table->clear();
}
以及如何将其连接到自定义功能测试对象的示例:
class myTestFunctional extends sfTestFunctional
{
public function get( $uri, $parameters = array(), $changeStack = true )
{
$this->clearEntityCache();
return parent::get( $uri, $parameters, $changeStack );
}
public function click( $name, $arguments = array(), $options = array() )
{
$this->clearEntityCache();
return parent::click( $name, $arguments, $options );
}
protected function clearEntityCache()
{
$manager = Doctrine_Manager::getInstance();
$connection = $manager->getCurrentConnection();
$tables = $connection->getTables();
foreach ( $tables as $table ) {
$table->clear();
}
}
}
因此,每次myTestFunctional
获取 url 或点击更改页面时,它都会清除内存中存储的任何 Doctrine 对象。不微妙,但有效,并且不会使测试本身更费力地编写!