2012-04-13 9 views
6

MySQL Connectorを使用し、EntityFramework 4.3を使用して、MySQL 5.5.19 DBに対していくつかの自動テストを実行するためにMSTestを使用しています。テストでネストされたTransactionScopeが失敗する

DBアクセスのクラスライブラリでTransactionScopeを使用して、必要なときにロールバックを実行しようとしています。さらに、私のテストコードでは、TransactionScopeを使用して、各テストの前にDBを既知の状態に戻したいと考えています。私はこれを達成するためにTestInitializeTestCleanupメソッドを使用します。これらはそうのように見える:初期化関数でありTransactionScopeオブジェクトの構築に基づいて

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

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

、私は(そう、既存の「周囲」1が存在しない、私は信じて、私は新しいトランザクション・スコープを取得しなければならないと考えていますこの ".RequiresNew"は、 ".Required"は同じ結果を生成するので、ここでは技術的に重要ではありません。タイムアウト値を指定しないので、デフォルトタイムアウトが与えられます。

私は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を指定しているので、MyTestInitialize関数で作成された「アンビエント」トランザクションスコープが使用されることを期待しています。

私のテストが失敗し、例外をスローするには、このDoOtherDessertStuff機能するように配置されているので、transScope.Complete();への呼び出しが起こらないとAddDessert機能でusingブロックの終了時にロールバックが自動的に行われます。

MyTestInitialize関数で作成されたアンビエントトランザクションスコープを使用しているため、私のテストAssertコールはトランザクションスコープロールバックが起きたために発生しません - 少なくともこれが起こっていると思います。 Transaction.Current.TransactionInformation.StatusTransactionStatus.Abortedであることを確認しましたので、これが起こっているかどうかはかなり確信しています。

グレートので、私はいくつかの私のusing行はこのように見えます見えます、私はまさに私が巣トランザクション・スコープではなく、周囲のいずれかを使用することを除き、上記のように見えるために私AddDesert方法を変更するだろうと思った:

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

ここでの目的は、これらのトランザクションスコープをネストすることができ、プロダクションコードのロールバックを発生させてから、自分のテストコードでAssertをチェックすることでした。

しかし、私が見つけています、私は次のエラーを取得することです:

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

アイデア?

+0

それが起こるスタックトレースとコードを投稿してください。 – usr

答えて

0

非常に良い質問です。 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()); 
      } 
     } 
    } 
関連する問題