Conflitto di test unitari supportati dallo sforzo

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

Domanda

Ho ereditato alcuni test con questo progetto. Stavano lavorando durante l'esecuzione sul database SQL, ma lentamente. Sto cercando di passare a utilizzare Effort.
.NET4.5, EF6.2, sforzo 1.3.10.

Ho due possibili problemi relativi ai miei test unitari.

Non importa se eseguo i test in parallelo o meno.

1) Se corro più di uno alla volta, ottengo

Salvare o accettare le modifiche non è riuscito perché più di un'entità di tipo "Center.Shared.Person" hanno lo stesso valore di chiave primaria. Assicurarsi che i valori della chiave primaria impostati in modo esplicito siano univoci. Assicurarsi che le chiavi primarie generate dal database siano configurate correttamente nel database e nel modello Entity Framework. Utilizzare Entity Designer per la prima configurazione del database / modello prima. Utilizzare l'API fluida "HasDatabaseGeneratedOption" o "DatabaseGeneratedAttribute" per la configurazione di Code First. ---> System.InvalidOperationException: il salvataggio o l'accettazione delle modifiche non è riuscito perché più entità di tipo "Center.Shared.Person" hanno lo stesso valore di chiave primaria. Garantire che i valori delle chiavi primarie impostati in modo esplicito siano univoci.Assicurarsi che le chiavi primarie generate dal database siano configurate correttamente nel database e nel modello Entity Framework.Utilizzare l'Entity Designer per la prima configurazione del database / modello Primo. Utilizzare l'API fluida "HasDatabaseGeneratedOption" o 'DatabaseGeneratedAttribute' per la prima configurazione del codice ..

Quindi sembra che i test non siano correttamente isolati.
Tracciando il codice, posso vedere che viene chiamato CreateTransient, ma a quanto pare non è abbastanza transitorio.

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

            return _connection;
        }
    }

Nella routine TestInitialize provo a ripristinare il database.

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

Questo è un codice altamente contorto, quindi se abbiamo bisogno di pubblicare più codice, è molto tempo prima che arriviamo al fondo della tana del coniglio. Probabilmente è meglio creare un PoC.

2) Se eseguo i test in modo indipendente, ho un problema diverso. Di nuovo, questi passarono contro SQL ma non lo sforzo.

    [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. 
    }

Crea consiste di

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

Trova consiste di

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

So che chiama CreateDbContext, ma traccia nel codice, per quanto posso dire che sembra essere lo stesso database con lo stesso ID.

Che cosa dovrebbe causare l'isolamento dei test?
E qualche idea sul perché Find smetterebbe di funzionare quando si utilizza un database in memoria?

Risposta accettata

Stavo cercando di utilizzare l'approccio implicito, in cui tutto è collegato tramite le impostazioni nel file app.config.
Ho iniziato ad avere più fortuna una volta abbandonato questo approccio e ho creato la connessione al database e l'ho impostato in modo esplicito.

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

La base Accessor crea copie del DB ad ogni turno, il che va bene fintanto che utilizza lo stesso DbConnection. Quindi l'ho impostato sull'accessor e quindi lo uso qui:

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

Infine, ho dovuto aggiungere un costruttore che ha preso un DbConnection a DbContext e ai suoi discendenti.

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

'Trova' ora funziona e i test non interferiscono tra loro.
Il prossimo passo è spingere tutto questo verso le classi base.



Related

Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow