2016-12-07 22 views
0

SQL Serverの統合テストでは、各テスト後にロールバックしてデータベースを一貫性のある状態に保つTransactionScopeでテストをラップします。Postgres、Npgsql、およびロールバックを使用した統合テスト

Postgres(または特にNpgsql)を使用すると、(コミットされていないトランザクションスコープ内であっても)個々の接続の外の選択がコミットされていないデータを読み取ることができないため、これは可能ではありません。

基本的なシナリオは、以下の簡略化されている:

[Test] 
public void ImplicitEnlist() 
{ 
    var connectionString = ConnectionString + ";enlist=true"; 
    using (var scope = new TransactionScope()) 
    { 
     using (var conn = new NpgsqlConnection(connectionString)) 
     { 
      conn.Open(); 
      Assert.That(conn.ExecuteNonQuery(@"INSERT INTO data (name) VALUES('test')"), Is.EqualTo(1)); 
     } 
     using (var conn = new NpgsqlConnection(connectionString)) 
     { 
      // -> this is false 
      Assert.That(conn.ExecuteScalar(@"SELECT COUNT(*) FROM data"), Is.EqualTo(1)); 
     } 
     scope.Rollback(); 
    } 
} 

誰でも人々がPostgresのデータベースでこれに近づいている方法を共有することはできますか?

+0

なぜテスト用に別々の接続が必要ですか? –

+0

統合テストは非常に幅広い機能テストであり、基礎となるクラスがどのように接続を利用するかとは切り離されています。 –

+0

コンテキストについては、SQL ServerからPostgresへの移行の可能性を調査しています。これが私がテストスイートでヒットした最初の問題でした。 –

答えて

1

github issueからの回答のコピー&ペースト:

私は本当に物事はあなたが思うように動作するようになっているとは思いません。同じTransactionScope内で2つの接続を開くと、分散トランザクションが実行されます。 PostgreSQLには2つの異なる接続があり、それぞれの接続はprepared transactionです。これは、2つの接続が互いに認識していること、または2つの準備されたトランザクションがやや関連していることを意味するものではありません。まだコミットされていないので、トランザクションの分離が適用され、各接続は他のトランザクションのコミットされていない変更を見ることができません。

要約すると、分散トランザクションとは、TransactionScopeでComplete()を呼び出すと、トランザクションがコミットするかどうかを確認するために2フェーズコミットプロトコルが使用されることを意味します。参加している取引が何らかの形で互いを認識していることを保証するものではありません。

私はこれがどのように機能するかは分かりませんが、私は分散トランザクションまたはPostgreSQL準備トランザクションの専門家ではないので間違っている可能性があります。これを閉じようとしていますが、あなたが私が言ったこととは逆の情報を見つけることができれば、再び開きます。

0

これを達成するための最良の方法は、セーブポイント(https://www.postgresql.org/docs/9.1/static/sql-rollback-to.html)を使用しているように見える - これはActiveRecordのはに対してそれを実装する方法であるPostgresは/ MySQLの(http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html

これにさらに掘りした後、結局のところ、我々が依存してきましたこれまでSQL Server上ではきれいでした。 SQL Server 2008(および.NET 3.5以降)は、同時に開かれていなければ、MSDTCのプロモーションを必要とせずにトランザクション内で複数の接続を処理できます。https://msdn.microsoft.com/en-us/library/ms172070(VS.90).aspx Postgresはこのシナリオでは同じ動作をしません。

テスト状態をロールバックするトランザクションに依存しないようにしました。代わりに、代わりにRespawn(https://github.com/jbogard/Respawn)を使用してdbを空の状態に戻しました。

関連する問題