3

我正在对我的 Symfony 1.4 项目进行功能测试,但它一直失败,因为它没有获取最新数据。

该测试组成一个新的站点条目,然后在该站点进行调查,然后将数据添加到调查中。这些中的每一个都在单独的页面和每个作品上。数据肯定存在于数据库中。保存最后一个表单survey_data 后,它会返回到调查页面,在该页面中应该获取调查详细信息以及添加到其中的所有数据项的列表。这适用于开发和生产环境,但在我的功能测试中,survey_data 列表为空。查看日志,它不会尝试从数据库中获取数据(Doctrine & Postgres)。但是,如果我在几秒钟后在浏览器中手动加载页面,列表就在那里,如果我运行一个直接进入页面的测试(不清除数据库),列表就在那里,所以测试登录有权查看该页面和内容,但一开始不会显示,

所以我的问题是,如何确保我的功能测试从数据库中获取最新数据,或者如何在将新项目保存到数据库后刷新本地数据对象缓存?

附加:我的功能测试扩展sfPHPUnitBaseFunctionalTestCase,我使用 sfBrowser 类来检查页面的内容并浏览它们

4

1 回答 1

0

问题似乎在于 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 对象。不微妙,但有效,并且不会使测试本身更费力地编写!

于 2013-11-21T00:40:42.420 回答