9

MSTest を使用して、MySQL コネクタ経由で EntityFramework 4.3 を使用して、MySQL 5.5.19 DB に対していくつかの自動テストを実行しています。

TransactionScope必要に応じてロールバックを実行するために、DB アクセス クラス ライブラリで使用しようとしています。さらに、私のテスト コードでは、TransactionScope各テストの前に DB を既知の状態に戻すために使用したいと考えています。TestInitializeおよびTestCleanupメソッドを使用してこれを実現します。それらは次のようになります。

[TestInitialize()]
public void MyTestInitialize()
{
   testTransScope = new TransactionScope(TransactionScopeOption.RequiresNew);
}

[TestCleanup()]
public void MyTestCleanup()
{
   Transaction.Current.Rollback();
   testTransScope.Dispose();
}

初期化関数内のオブジェクトの構築に基づいてTransactionScope、新しいトランザクション スコープを取得する必要があると思います (「周囲の」トランザクション スコープは存在しないため、この「.RequiresNew」はここでは技術的に重要ではないと考えています。 .Required" は同じ結果を生成します。タイムアウト値を指定していないため、デフォルトのタイムアウトが提供されます。これは 60 秒であると理解しています。指定されたテストを実行するのに十分な時間です。

AddDessert(DessertBiz dessertBizObject)部分的に次のような関数と呼ばれる関数があります。

using (var transScope = new TransactionScope(TransactionScopeOption.Required))
{
   try
   {
      // ...
      context.Desserts.Add(dessert);
      context.SaveChanges();
      var dessertId = dessert.Id;
      DoOtherDessertStuff(dessertId, dessertBizObject);
      transScope.Complete();
   }
   catch (InvalidOperationException ex)
   {
      Console.WriteLine(ex.ToString());
   }
}

そして、この関数は私のテストの1つによって呼び出されます。

ここで指定したのでTransactionScopeOption.Required、関数によって作成された "ambient" トランザクション スコープが使用されることを期待していMyTestInitializeます。

私のテストは、このDoOtherDessertStuff関数が失敗して例外をスローするように調整されているため、呼び出しは行われず、関数内のブロックをtransScope.Complete();終了するとロールバックが自動的に発生します。usingAddDessert

私がここで抱えている問題は、MyTestInitialize関数で作成されたアンビエント トランザクション スコープを使用するため、トランザクション スコープのロールバックが発生したため、テストAssert呼び出しが発生しないことです。少なくともこれが起こっていると思います。それTransaction.Current.TransactionInformation.StatusTransactionStatus.Abortedであることを確認したので、これが起こっていると確信しています。

AddDesert素晴らしいので、アンビエント スコープを使用するのではなく、トランザクション スコープをネストすることを除いて、メソッドを上記とまったく同じように変更すると思いました。一部のusing行は次のようになります。

using (var transScope = new TransactionScope(TransactionScopeOption.RequiresNew))

ここでの意図は、これらのトランザクション スコープをネストし、実稼働コードでロールバックを発生させてからAssert、テスト コードで s をチェックできるようにすることでした。

しかし、私が見つけているのは、次のエラーが発生することです。

System.IO.IOException: トランスポート接続からデータを読み取ることができません: 接続先が一定時間後に適切に応答しなかったために接続の試行が失敗したか、接続されたホストが応答しなかったために確立された接続が失敗しました。

アイデア?

4

1 に答える 1

1

とても良い質問です。ロールバック後にtestmethod内でdatacontextを参照すると、使用できなくなります。あなたはそれを抑制する必要があります。必要なオプションを指定する必要はありません。これはデフォルトのオプションです。

試験方法:

  [TestMethod()]
    public void CreateTestCheckContextCorrectly()
    {
        MailJobController target = new MailJobController();

        target.AddDessert("dessert for Omer");
        //With suppress, even if you rollback ambient trans, suppress will ignore ambient trans. You need to reference new context, previous context from controller may be disposed.
        using (var suppressscope = new TransactionScope(TransactionScopeOption.Suppress))
        {
            var newdbcontextref = new DbEntities();

            int recordcount = newdbcontextref.StatusDefinitions.Where(x => x.Name == "dessert for Omer").Count();

            Assert.AreEqual(0, recordcount);
        }
    }

コントローラ方式:

 public void AddDessert(string dessert)
   {
       using (var transScope = new TransactionScope())
       {
           try
           {
               // ...
               StatusDefinition statusDefinition = new StatusDefinition() {Name = dessert};
               db.StatusDefinitions.AddObject(statusDefinition);
               db.SaveChanges();
               Console.WriteLine("object id:"+statusDefinition.StatusDefinitionId);
               throw new Exception("hee hee");
               transScope.Complete();
           }
           catch (Exception ex)
           {
               Console.WriteLine(ex.ToString());
           }
       }
   }
于 2012-04-19T06:23:34.427 に答える