2012-04-13 50 views
6

Używam MSTest do uruchomienia niektórych testów automatycznych na bazie danych MySQL 5.5.19 DB przez złącze MySQL i użycie EntityFramework 4.3.Zagnieżdżone TransactionScope kończy się niepowodzeniem w testach

Próbuję użyć TransactionScope w mojej bibliotece klasy dostępu DB, aby wykonać wycofanie, gdy jest to konieczne. Dodatkowo, w moim kodzie testowym chcę użyć TransactionScope, aby przywrócić DB do znanego stanu przed każdym testem. Używam metod TestInitialize i TestCleanup, aby to osiągnąć. Ci wyglądać tak:

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

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

oparciu o budowę obiektu tam w funkcji initialize TransactionScope, wierzę, że powinno być uzyskanie nowego zakresu transakcji (nie jest „otoczenia” jeden istniejący więc wierzę ten ".RequiresNew" nie ma tutaj znaczenia technicznego, ponieważ ".Required" dałby taki sam wynik. Ponieważ nie określam wartości limitu czasu, zapewnia mi domyślny limit czasu, który rozumiem jako 60 sekund. . czas na mój dany test uruchomić

mam funkcję o nazwie AddDessert(DessertBiz dessertBizObject) która wygląda po części coś takiego:

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()); 
    } 
} 

Ta funkcja jest wywoływana przez jeden z moich testów.

Ponieważ podałem tutaj TransactionScopeOption.Required, oczekuję, że użyje on zakresu transakcji "otoczenia" utworzonego przez funkcję MyTestInitialize.

Mój testowy jest umieszczony, aby ten DoOtherDessertStuff funkcję fail i wyjątek, więc wywołanie transScope.Complete(); nie zdarza i wycofywania następuje automatycznie po wyjściu z bloku w funkcji AddDessertusing.

Mam problem tutaj jest to, że ponieważ używa zakresu transakcji otoczenia utworzonego w funkcji MyTestInitialize, moja próba Assert domaga się nie zdarzają, ponieważ zakres wycofywania transakcja się - przynajmniej to, co myślę dzieje. Sprawdziłem, czy Transaction.Current.TransactionInformation.Status jest TransactionStatus.Alced, więc jestem pewien, że to właśnie się dzieje.

Wielki, więc myślałem, że chciałbym zmienić mój sposób AddDesert wyglądać dokładnie tak, jak powyżej, z tym, że chciałbym gniazdo zakres transakcji, zamiast przy użyciu jednego z otoczenia, niektóre moje using linia wygląda wygląda następująco:

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

Chodziło o to, że mógłbym zagnieździć te zakresy transakcji, pozwolić na wycofanie w moim kodzie produkcyjnym, a następnie sprawdzić mój kod testowy pod kątem moich Assert.

Ale co ja znalezieniem jest to, że pojawia się następujący błąd:

System.IO.IOException: Nie można odczytać danych z połączenia transportowego: Próba połączenia nie powiodło się, ponieważ połączona strona nie odpowiedziała poprawnie po czas lub nawiązane połączenie nie powiodło się, ponieważ podłączony host nie odpowiedział.

Pomysły?

+0

Proszę opublikować StackTrace i kod gdzie to się dzieje. – usr

Odpowiedz

0

Bardzo dobre pytanie. Kiedy odwołujesz się do datakontekstu wewnątrz metody testowej po wycofaniu, nie będzie on dostępny. Musisz to powstrzymać. Nie musisz podawać wymaganej opcji.Jest to domyślna opcja.

test metoda:

[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); 
     } 
    } 

metoda Kontroler:

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()); 
      } 
     } 
    } 
Powiązane problemy