この問題は、Doctrine が実行中に更新するオブジェクトをキャッシュすることにあるようです。これは、実稼働環境での各 Web リクエストの後にクリアされます (実行ごとに 1 つのリクエスト)。ただし、テスト環境では、すべてが同じ実行で発生しているため、リクエスト間で持続するように見えます。
たとえば、新しいアイテムをリストに追加するプロセスをテストするときは面倒です-リストはメモリ内にあり(テストブラウザは以前にそのページにアクセスしました)、新しいアイテムが作成され、保存されますが、それらの間のリンクはありませんメモリ内で形成されます。
関連オブジェクトの対象を絞った更新
強制的に更新しようとしているオブジェクトがわかっている場合は、次のことができます。
$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();
}
}
}
したがって、URL を取得するかクリックしてページを変更するたびmyTestFunctional
に、メモリに保存されている Doctrine オブジェクトが消去されます。微妙ではありませんが、効果的であり、テスト自体を書くのが面倒になることはありません!