web-dev-qa-db-fra.com

Se moquer ou simuler DbEntityEntry ou créer un nouveau DbEntityEntry

Pour faire suite à mon autre question sur le fait de se moquer de DbContext.Set J'ai une autre question concernant le fait de se moquer de EF Code First.

J'ai maintenant une méthode pour ma mise à jour qui ressemble à:

if (entity == null)
    throw new ArgumentNullException("entity");

Context.GetIDbSet<T>().Attach(entity);
Context.Entry(entity).State = EntityState.Modified;
Context.CommitChanges();

return entity;

Le contexte est une interface de mon propre DbContext.

Le problème que je rencontre est: comment gérer les

Context.Entry(entity).State.

J'ai parcouru ce code et cela fonctionne quand j'ai un réel DbContext en tant qu'implémentation de mon interface de contexte. Mais quand je mets mon faux contexte là, je ne sais pas comment le gérer.

Il n'y a pas de constructeur pour une classe DbEntityEntry, je ne peux donc pas en créer un nouveau dans mon faux contexte.

Quelqu'un a-t-il réussi à simuler ou à simuler DbEntityEntry dans vos solutions CodeFirst?

Ou existe-t-il une meilleure façon de gérer les changements d'état?

59
taylonr

Comme dans l’autre cas, vous devez ajouter un niveau supplémentaire d’indirection:

interface ISalesContext
{
    IDbSet<T> GetIDbSet<T>();
    void SetModified(object entity)
}

class SalesContext : DbContext, ISalesContext
{
    public IDbSet<T> GetIDbSet<T>()
    {
        return Set<T>();
    }

    public void SetModified(object entity)
    {
        Entry(entity).State = EntityState.Modified;
    }
}

Ainsi, au lieu d'appeler l'implémentation, vous appelez simplement SetModified.

91
Diego Mijelshon

Trouvé cette question lorsque je devais effectuer des tests unitaires avec Moq, pas besoin de votre propre interface. Je voulais définir des champs spécifiques pour qu'ils ne soient pas modifiés, mais la méthode SetModified peut également être utilisée avec object. 

DbContext:

public class AppDbContext : DbContext
{   
    ...
    public virtual void SetModified(GuidEntityBase entity)
    {
        Entry(entity).State = EntityState.Modified;
        Entry(entity).Property(x => x.CreatedDate).IsModified = false;
        Entry(entity).Property(x => x.CreatedBy).IsModified = false;
    }
    ...
}

Tester:

var mockContext = new Mock<AppDbContext>();
mockContext.Setup(c => c.MyDbSet).Returns(mockMyDbSet.Object);
mockContext.Setup(c => c.SetModified(It.IsAny<GuidEntityBase>()));
0
Ogglas