Мой вопрос и код основаны на Примерах модульных тестов Code First Entity Frameworkв блоге. Я использую SQL Compact 4.0, и поэтому мои модульные тесты работают с реальной базой данных, используя реальные данные, подобные тем, что описаны в сообщении в блоге.
Я хочу заполнить мою производственную базу данных значениями по умолчанию в некоторых таблицах, но при выполнении модульных тестов я хочу добавить дополнительные данные и обновить некоторые значения по умолчанию.
Я создал собственный класс Initializer, который заполняет базу данных значениями по умолчанию. Для своих модульных тестов я создал еще один пользовательский Initializer, который наследуется от первого, который выполняет конкретное заполнение и/или модификации теста:
public class NerdDinnersInitializer : DropCreateDatabaseIfModelChanges
{
protected override void Seed(NerdDinners context)
{
var dinners = new List
{
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();
}
}
Я также использую базовый класс для своих модульных тестов, который инициализирует тестовую базу данных следующим образом:
[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);
}
}
}
] Реальный модульный тест выглядит следующим образом:
[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);
}
}
Когда я запускаю тест, запрос Linq, который извлекает сохраненный ужин, завершается ошибкой с сообщением «Экземпляр ObjectContext удален и больше не может использоваться для операций, требующих соединения». исключение. Я не могу понять, почему.
Является ли то, что я здесь делаю, приемлемым шаблоном, и может ли кто-нибудь пролить свет на то, почему это не работает?
Спасибо.