2012-03-28 11 views
5

Moje pytanie i kod jest oparty na poście na blogu Code First Entity Framework Unit Test Examples. Używam SQL Compact 4.0 i jako takie moje testy jednostkowe działają w oparciu o rzeczywistą bazę danych przy użyciu rzeczywistych danych podobnych do tego, co jest opisane w poście na blogu.Kod struktury jednostki Najpierw: Jak zasiać bazę danych do testowania jednostkowego

Chcę zasiać moją produkcyjną bazę danych wartościami domyślnymi w niektórych tabelach, ale podczas uruchamiania testów jednostkowych chcę dodać dodatkowe dane i zaktualizować niektóre z domyślnych wartości.

Utworzono niestandardową klasę inicjalizatora, która zasiewa bazę danych z wartościami domyślnymi. Dla moich testów jednostkowych Stworzyłem kolejny niestandardowy inicjująca, która dziedziczy z pierwszego, dokłada test specyficzny siewu i/lub modyfikacje:

public class NerdDinnersInitializer : DropCreateDatabaseIfModelChanges<NerdDinners> 
{ 
    protected override void Seed(NerdDinners context) 
    { 
     var dinners = new List<Dinner> 
          { 
           new Dinner() 
            { 
             Title = "Dinner with the Queen", 
             Address = "Buckingham Palace", 
             EventDate = DateTime.Now, 
             HostedBy = "Liz and Phil", 
             Country = "England" 
            } 
          }; 

     dinners.ForEach(d => context.Dinners.Add(d)); 

     context.SaveChanges(); 
    } 
} 

public class NerdDinnersInitializerForTesting : NerdDinnersInitializer 
{ 
    protected override void Seed(NerdDinners context) 
    { 
     base.Seed(context); 

     var dinner = context.Dinners.Where(d => d.Country == "England").Single(); 
     dinner.Country = "Ireland"; 

     context.SaveChanges(); 
    } 
} 

Używam również klasę bazową dla moich testów jednostkowych, które inicjuje testowej bazy danych jak tak:

[TestClass] 
public abstract class TestBase 
{ 
    protected const string DbFile = "test.sdf"; 
    protected const string Password = "1234567890"; 
    protected NerdDinners DataContext; 

    [TestInitialize] 
    public void InitTest() 
    { 
     Database.DefaultConnectionFactory = new SqlCeConnectionFactory("System.Data.SqlServerCe.4.0", "", 
       string.Format("Data Source=\"{0}\";Password={1}", DbFile, Password)); 
     Database.SetInitializer(new NerdDinnersInitializerForTesting()); 

     DataContext = new NerdDinners(); 
     DataContext.Database.Initialize(true); 
    } 

    [TestCleanup] 
    public void CleanupTest() 
    { 
     DataContext.Dispose(); 

     if (File.Exists(DbFile)) 
     { 
      File.Delete(DbFile); 
     } 
    } 
} 

rzeczywiste testy jednostkowe wygląda następująco:

[TestClass] 
public class UnitTest1 : TestBase 
{ 
    [TestMethod] 
    public void TestMethod1() 
    { 
     var dinner = new Dinner() 
          { 
           Title = "Dinner with Sam", 
           Address = "Home", 
           EventDate = DateTime.Now, 
           HostedBy = "The wife", 
           Country = "Italy" 
          }; 

     DataContext.Dinners.Add(dinner); 
     DataContext.SaveChanges(); 

     var savedDinner = (from d in DataContext.Dinners 
          where d.DinnerId == dinner.DinnerId 
          select d).Single(); 

     Assert.AreEqual(dinner.Address, savedDinner.Address); 
    } 
} 

Kiedy uruchomić test kwerendy Linq, który pobiera savedDinner nie z "Instancja ObjectContext została usunięta i nie można jej już używać do operacji wymagających połączenia." wyjątek. Nie mogę zrozumieć dlaczego.

Czy to, co tutaj robię, jest akceptowalnym wzorcem i czy ktoś może rzucić nieco światła na to, dlaczego to nie działa?

Dzięki.

+0

Nie widzę powodu, dla którego kontekst obiektu został usunięty. Czy możesz debugować swój test jednostki i umieścić punkt przerwania w metodzie savechanges i sprawdzić czy format danych nie jest pusty? następnie przejdź do następnej linii i sprawdź, czy datacontext jest pusty. – daryal

+0

Witaj Daryal, datakontekst nie jest pusty w obu przypadkach. DataContext.SaveChanges(); działa dobrze, jest to zapytanie Linq po nim, które nie działa, nawet jeśli datacontext nie jest pusty. –

+0

Mogę foreach nad DataContext.Dinners bez problemu. Uwaga: błąd, który otrzymałem stwierdził, że ObjectContext został usunięty, a nie DataContext. Nie wiem, czy ObjectContext jest taki sam jak DataContext w zapytaniu Linq. W każdym razie, wykonując następujące czynności: var initDb = new SvDataContext(); initDb.Database.Initialize (true); DataContext = new SvDataContext(); w mojej metody InitTest rozwiązuje problem. –

Odpowiedz

3

Tego samego dnia spotkałem się z podobnym problemem. Problem jest spowodowany przez klauzulę where w metodzie seed. Rozwiązaniem tego (na razie) jest przepisanie to:

var dinner = context.Dinners.ToList().Where(d => d.Country == "England").Single(); 

Chociaż nie jest wydajny (wszystkie obiekty są pobierane z bazy danych i filtrowanie będzie odbywać się w pamięci), to nie rozwiąże ObjectDisposedException w moich testów jednostkowych. W moim przypadku mam tylko kilka obiektów, więc na razie mogę z tym żyć.

+0

Dziękuję za odpowiedź Jos. Jak wyizolowałeś problem? –

+1

Zajęło mi trochę czasu, aby dowiedzieć się, ponieważ myślałem, że problem został spowodowany przez konfigurację IoC, z powodu DisposedException. Powinienem był wiedzieć, że nic tam nie zmieniłem i to działało wcześniej. Miałem scenariusz roboczy, zmodyfikowałem kod źródłowy dodatkowymi modelami (również tam, gdzie wprowadzono klauzulę), ciągle komentowałem nowo wprowadzony kod, dopóki problem nie wystąpił. Odkomentuj kod klauzuli where i wyjątek powrócił. Proste, ale skuteczne śledzenie błędów w przypadku zamkniętych frameworków źródłowych Cię zawodzi. –

Powiązane problemy