Shim DbContext ctor pour les tests unitaires Effort

effort entity-framework microsoft-fakes shim unit-testing

Question

J'aimerais intercepter var context = new MyDbContext() pour renvoyer un appel de constructeur différent à la place.

Le grand avantage d’ EFfort est qu’il vous permet de configurer une base de données facile en mémoire pour les tests unitaires.

var connection = Effort.DbConnectionFactory.CreateTransient();
var testContext = new MyDbContext(connection);

Mais vous devrez alors injecter ce context dans votre référentiel.

var connection = Effort.DbConnectionFactory.CreateTransient();
var testContext = new MyDbContext(connection);

Est-il possible d'intercepter simplement var context = new MyDbContext() , afin qu'il renvoie le testContext ?

var connection = Effort.DbConnectionFactory.CreateTransient();
var testContext = new MyDbContext(connection);

Réponse acceptée

(Edit: je viens de me rendre compte que cela ne renvoie pas en réalité l'appel de l'autre utilisateur

Deviner. Assez simple si vous savez le faire:

        [TestMethod]
        public void Should_have_a_name_like_this()
        {
            // Arrange
            var connection = Effort.DbConnectionFactory.CreateTransient();
            ShimSolrDbContext.Constructor = context => new SolrDbContext(connection);

            // Act


            // Assert

        }

Et comme d'habitude, EFfort a besoin de ce constructeur dans la classe DbContext:

        [TestMethod]
        public void Should_have_a_name_like_this()
        {
            // Arrange
            var connection = Effort.DbConnectionFactory.CreateTransient();
            ShimSolrDbContext.Constructor = context => new SolrDbContext(connection);

            // Act


            // Assert

        }

Mais cela signifie que le repo ignore parfaitement la connexion transitoire spéciale:

        [TestMethod]
        public void Should_have_a_name_like_this()
        {
            // Arrange
            var connection = Effort.DbConnectionFactory.CreateTransient();
            ShimSolrDbContext.Constructor = context => new SolrDbContext(connection);

            // Act


            // Assert

        }

Réponse populaire

Vous avez deux options possibles. Utiliser des usines ou via une programmation orientée aspect (comme PostSharp)

référençant cet article: http://www.progware.org/Blog/post/Interception-and-Interceptors-in-C-(Aspect-oriented-programming).aspx

Utilisation de PostSharp (AOP)

PostSharp est un excellent outil et peut réaliser l'interception la plus propre possible (ce qui signifie qu'aucune modification n'est apportée à vos classes ni à la génération d'objets même si vous n'utilisez pas vos fabriques pour la création d'objets et / ou les interfaces), mais ce n'est pas une bibliothèque libre. Plutôt que de créer des mandataires lors de l'exécution, il injecte du code lors de la compilation et modifie donc votre programme initial de manière transparente pour ajouter une interception de méthode.
.....
La chose intéressante dans ceci est que vous ne changez rien d'autre dans votre code, ainsi votre objet peut toujours être généré en utilisant le nouveau mot-clé.

Utiliser DI et Factory-pattern

Personnellement, je préfère l’approche des modèles d’usine, mais vous semblez devoir accepter d’injecter des dépendances dans vos classes.

public interface IDbContextFactory<T> where T : DbContext {
    T Create();
}

public class TestDbContextFactory : IDbContextFactory<MyDbContext> {
    public MyDbContext Create() {
        var connection = Effort.DbConnectionFactory.CreateTransient();
        var testContext = new MyDbContext(connection);
        return testContext;
    }
}

public class FooRepository {
    MyDbContext _context;
    public FooRepository(IDbContextFactory<MyDbContext> factory) { 
        _context = factory.Create(); 
    }
}



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