Mi pregunta y código se basan en la publicación de blog Code First Entity Framework Unit Test Examples. Estoy usando SQL Compact 4.0 y, como tal, mis pruebas unitarias se ejecutan en la base de datos real utilizando datos reales similares a los que se describen en la publicación del blog.Código de Entity Framework Primero: Cómo inicializar una base de datos para pruebas de unidades
Quiero inicializar mi base de datos de producción con los valores predeterminados en algunas de las tablas, pero cuando ejecuto las pruebas de mi unidad deseo agregar datos adicionales y actualizar algunos de los valores predeterminados.
He creado una clase de inicializador personalizada que inicia la base de datos con los valores predeterminados. Para mis pruebas de unidad que he creado otro inicializador personalizado que hereda de la primera que hace la siembra de la prueba específica y/o modificaciones:
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();
}
}
También uso una clase base para mis pruebas de unidad que inicializa la base de datos de prueba como por lo que:
[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);
}
}
}
la prueba de unidad real se parece a esto:
[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);
}
}
Cuando ejecuto la prueba de la consulta LINQ que obtiene el savedDinner falla con el "La instancia de ObjectContext se ha eliminado y ya no se puede usar para operaciones que requieren una conexión". excepción. No puedo entender por qué.
Es lo que estoy haciendo aquí un patrón aceptable y ¿alguien puede arrojar algo de luz sobre por qué esto no está funcionando?
Gracias.
No veo ninguna razón por la que se elimine el contexto del objeto. ¿Puedes depurar tu prueba de unidad y poner un punto de ruptura para guardar el método de cambio y verificar si el contexto de datos no es nulo? luego, establezca la siguiente línea y verifique si datacontext es nulo. – daryal
Hola, Daryal, el contexto de datos no es nulo en ninguno de los casos. DataContext.SaveChanges(); funciona bien, es la consulta Linq después de que falla aunque el contexto de datos no es nulo. –
Puedo foreach sobre los DataContext.Dinners sin ningún problema. Tenga en cuenta que el error que he recibido indica que ObjectContext ha sido eliminado, no DataContext. No sé si ObjectContext es lo mismo que DataContext en la consulta de Linq. De todos modos, haciendo lo siguiente: var initDb = new SvDataContext(); initDb.Database.Initialize (true); DataContext = new SvDataContext(); en mi método InitTest corrige el problema. –