Conflit de tests unitaires pris en charge par l'effort

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

Question

J'ai hérité de quelques tests avec ce projet. Ils travaillaient lors de l'exécution sur la base de données SQL, mais lentement. J'essaie de passer à utiliser Effort.
.NET4.5, EF6.2, Effort 1.3.10.

J'ai deux problèmes éventuellement liés à mes tests unitaires.

Peu importe si je lance les tests en parallèle ou non.

1) Si je cours plus d’un à la fois, je reçois

L'enregistrement ou l'acceptation des modifications a échoué car plusieurs entités de type 'Center.Shared.Person' ont la même valeur de clé primaire. Assurez-vous que les valeurs de clé primaire explicitement définies sont uniques. Assurez-vous que les clés primaires générées par la base de données sont correctement configurées dans la base de données et dans le modèle Entity Framework. Utilisez le concepteur d'entité pour la configuration de base de données d'abord / modèle d'abord. Utilisez l'API couramment «HasDatabaseGeneratedOption» ou «DatabaseGeneratedAttribute» pour la configuration Code First. Assurez-vous que les valeurs de clé primaire définies explicitement sont uniques Assurez-vous que les clés primaires générées par la base de données sont configurées correctement dans la base de données et dans le modèle Entity Framework. Utilisez la configuration Entity Designer pour Database First / Model First. 'DatabaseGeneratedAttribute' pour la configuration du code premier.

Il semble donc que les tests ne sont pas correctement isolés.
En parcourant le code, je peux voir que CreateTransient est appelé, mais il n’est apparemment pas assez transitoire.

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

            return _connection;
        }
    }

Dans la routine TestInitialize, j'essaie de réinitialiser la base de données.

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

Il s'agit d'un code extrêmement compliqué. Par conséquent, si nous devons publier plus de code, il faudra beaucoup de temps avant d'atteindre le fond du terrier du lapin. Probablement mieux créer un PoC.

2) Si je lance les tests indépendamment, j'obtiens un problème différent. Encore une fois, ceux-ci sont passés contre SQL mais pas avec 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. 
    }

Créer 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;
    }

Trouver se compose de

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

Je sais qu'il appelle CreateDbContext, mais en traçant dans le code, autant que je sache, il semble que ce soit la même base de données avec le même ID.

Qu'est-ce qui devrait provoquer l'isolement des tests?
Et des idées sur la raison pour laquelle Find cesserait de fonctionner lors de l'utilisation d'une base de données en mémoire?

Réponse acceptée

J'essayais d'utiliser l'approche implicite, où tout est connecté via les paramètres du fichier app.config.
J'ai commencé à avoir plus de chance une fois que j'ai abandonné cette approche et créé la connexion à la base de données et la configurée explicitement.

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

L'accesseur de base crée des copies de la base de données à chaque tour, ce qui est correct tant qu'il utilise le même connecteur DbConnection. Donc, je mets cela sur l'accesseur et ensuite l'utiliser ici:

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

Enfin, j'ai dû ajouter un constructeur qui a pris DbConnection à DbContext et à ses descendants.

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

'Trouver' fonctionne maintenant et les tests n'interfèrent pas les uns avec les autres.
La prochaine étape consiste à tout réduire aux classes de base.



Related

Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi