2012-03-28 10 views
5

La mia domanda e il mio codice si basano sul post del blog Code First Entity Framework Unit Test Examples. Sto usando SQL Compact 4.0 e in quanto tale i miei test di unità sono in esecuzione contro il database reale utilizzando dati reali simili a ciò che viene descritto nel post del blog.Codice quadro entità Primo: come effettuare il seeding di un database per il test dell'unità

Desidero seminare il mio database di produzione con valori predefiniti in alcune tabelle ma durante l'esecuzione dei test di unità, desidero aggiungere ulteriori dati e aggiornare alcuni valori predefiniti.

Ho creato una classe Initializer personalizzata che semina il database con i valori predefiniti. Per i miei test di unità ho creato un altro Initializer personalizzato che eredita dal primo che fa la semina il test specifici e/o modifiche:

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

Io uso anche una classe di base per il mio test di unità che inizializza il database di test come così:

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

il test di unità reale si presenta così:

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

Quando eseguo il test della query LINQ che recupera il savedDinner non riesce con il "L'istanza di ObjectContext è stata eliminata e non può più essere utilizzata per operazioni che richiedono una connessione." eccezione. Non riesco a capire perché.

È quello che sto facendo qui un modello accettabile e qualcuno può far luce sul perché questo non funziona?

Grazie.

+0

Non riesco a vedere perché il contesto dell'oggetto sia stato eliminato. È possibile eseguire il debug del test dell'unità e impostare un punto di interruzione sul metodo di salvataggio e verificare se datacontext non è nullo? quindi impostare setp alla riga successiva e verificare se datacontext è nullo. – daryal

+0

Ciao Daryal, il datacontext non è nullo in entrambi i casi. The DataContext.SaveChanges(); funziona bene, è la query di Linq dopo che fallisce anche se il datacontext non è nullo. –

+0

Posso scavalcare DataContext.Dinners senza problemi. Nota, l'errore che ho dichiarato che l'ObjectContext è stato eliminato, non il DataContext. Non so se ObjectContext è lo stesso di DataContext nella query di Linq. Ad ogni modo, facendo quanto segue: var initDb = new SvDataContext(); initDb.Database.Initialize (true); DataContext = new SvDataContext(); nel mio metodo InitTest risolve il problema. –

risposta

3

Mi sono imbattuto in un problema simile questa mattina. Il problema è causato dalla clausola where nel metodo seed. Una soluzione per questo (per ora) sta riscrivendo questo:

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

Anche se non efficiente (tutti gli oggetti vengono recuperati dal database e il filtraggio sarà fatto in memoria), ha fatto risolvere il ObjectDisposedException nel mio test di unità. Nel mio caso ho solo pochi oggetti, quindi posso conviverci per ora.

+0

Grazie per la tua risposta Jos. Come hai isolato il problema? –

+1

Mi ci è voluto un po 'per capire perché stavo pensando che il problema fosse causato dalla configurazione IoC, a causa di DisposedException. Avrei dovuto saperlo meglio, non ho cambiato nulla e prima funzionava. Avevo uno scenario di lavoro, ho modificato il codice seme con altri modelli (con la clausola where introdotto), continuando a commentare il codice appena introdotto fino a quando il problema non si verificava. Rimuovi il commento dal codice della clausola where e dall'eccezione. Tracciamento degli errori semplice ma efficace nel caso in cui i framework di origine chiusi ti abbandonino. –

Problemi correlati