Pruebas unitarias apoyadas esfuerzo esfuerzo

c# effort entity-framework-6 unit-testing vstest

Pregunta

He heredado algunas pruebas con este proyecto. Estaban trabajando cuando se ejecutaban contra la base de datos SQL, pero lentamente. Estoy tratando de cambiar a usar Esfuerzo.
.NET4.5, EF6.2, Esfuerzo 1.3.10.

Tengo dos problemas posiblemente relacionados con mis pruebas de unidad.

No importa si ejecuto las pruebas en paralelo o no.

1) Si corro más de uno a la vez, obtengo

Error al guardar o aceptar los cambios porque más de una entidad del tipo 'Center.Shared.Person' tiene el mismo valor de clave principal. Asegúrese de que los valores de clave principal establecidos explícitamente son únicos. Asegúrese de que las claves primarias generadas por la base de datos estén configuradas correctamente en la base de datos y en el modelo de Entity Framework. Utilice el diseñador de entidades para la configuración de Database First / Model First. Use la API fluida 'HasDatabaseGeneratedOption "o' DatabaseGeneratedAttribute 'para la configuración de Code First. ---> System.InvalidOperationException: El guardar o aceptar cambios falló porque más de una entidad del tipo' Center.Shared.Person 'tiene el mismo valor de clave principal. Asegúrese de que los valores de clave primaria explícitamente establecidos sean únicos. Asegúrese de que las claves primarias generadas por la base de datos estén configuradas correctamente en la base de datos y en el modelo de Entity Framework. Use el Diseñador de entidades para la configuración de Base de datos primero / Modelo primero. Use la API fluida 'HasDatabaseGeneratedOption "o 'DatabaseGeneratedAttribute' para la configuración de Code First ..

Así que parece que las pruebas no están adecuadamente aisladas.
Al rastrear a través del código, puedo ver que se llama a CreateTransient, pero aparentemente no es lo suficientemente transitorio.

    public DbConnection CreateConnection(string nameOrConnectionString)
    {
        lock (_lock)
        {
            if (_connection == null)
            {
                _connection = Effort.DbConnectionFactory.CreateTransient();
            }

            return _connection;
        }
    }

En la rutina TestInitialize trato de restablecer la base de datos.

    [TestInitialize]
    public override void Initialize()
    {
        db.Database.Delete();
        db.Database.CreateIfNotExists();
        db.Database.Initialize(true);

Este es un código altamente complicado, por lo que si necesitamos publicar más código, es mucho tiempo antes de llegar al fondo del agujero del conejo. Probablemente sea mejor crear un PoC.

2) Si ejecuto las pruebas de forma independiente, tengo un problema diferente. Nuevamente, estos pasaron contra SQL pero no Effort.

    [TestMethod]
    public void ClientAccessorTests_Find()
    {
        Client result;
        Client client = new Client()
        {
            Complete = false,
            HeadOfHousehold = true,
            PersonID = _person.PersonID
        };

        _accessor.Create(client, _accessor.DefaultConnectionContext);

        result = _accessor.Find(new object[] { client.ClientID }, _accessor.DefaultConnectionContext);

        Assert.IsNotNull(result);  // Fails with Assert.IsNotNull failed. 
    }

Crear consiste en

    public virtual EntityType Create(EntityType entity, ConnectionContext connectionContext)
    {
        IsContextValid(connectionContext);
        if (entity == null) throw new ArgumentException("", "entity");

        using (var db = CreateDbContext<DbContextType>(connectionContext))
        {
            db.Set<EntityType>().Add(entity);
            db.SaveChanges();
        }

        return entity;
    }

Encontrar consiste en

    public virtual EntityType Find(object[] primaryKey, ConnectionContext connectionContext)
    {
        IsContextValid(connectionContext);
        if (primaryKey == null || primaryKey.Length == 0) throw new ArgumentException("", "primaryKey");

        using (var db = CreateDbContext<DbContextType>(connectionContext))
        {
            return db.Set<EntityType>().Find(primaryKey);
        }
    }

Sé que está llamando a CreateDbContext, pero el rastreo en el código, por lo que puedo decir, parece ser la misma base de datos con la misma ID.

¿Qué es lo que debería hacer que las pruebas sean aisladas?
¿Y alguna idea sobre por qué Find dejaría de funcionar al usar una base de datos en memoria?

Respuesta aceptada

Estaba tratando de usar el enfoque implícito, donde todo está conectado a través de la configuración en el archivo app.config.
Comencé a tener mejor suerte una vez que abandoné ese enfoque, creé la conexión de la base de datos y la configuré explícitamente.

        System.Data.Common.DbConnection connection = new EffortProviderFactory("").CreateConnection("");
        _accessor = new ClientAccessor();
        _accessor.Connection = connection;
        db = new EntitiesDb(connection);

El Accessor base crea copias de la base de datos en cada turno, lo que está bien siempre que utilice la misma DbConnection. Así que lo puse en el accesorio y luego lo uso aquí:

        if (_connection == null) {   // this is the path for the application
            if (connectionContext == null) {
                ret = new T();
            } else {
                ret = (T)Activator.CreateInstance(typeof(T), new object[] { connectionContext });
            }
        } else {  // this is the path for unit tests.
            ret = (T)Activator.CreateInstance(typeof(T), new object[] { _connection });
        }

Finalmente, tuve que agregar un constructor que llevó una DbConnection a DbContext y sus decendientes.

    public EntitiesDb(DbConnection connection) : base(connection) { }

'Buscar' ahora funciona y las pruebas no interfieren entre sí.
El siguiente paso es empujar todo esto a las clases base.



Related

Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow