Frage

Ich erstelle ein Mock-IDbSet, um unter anderem Unit-Tests von Entity-Framework-Klassen zu ermöglichen.

Ich habe jedoch wirklich Probleme, Änderungen zu erkennen oder überhaupt herauszufinden, wie das geht.Hier sind meine bisherigen Kurse...

public interface IReportContext
{
    IDbSet<Report> Reports {get;}
    public int SaveChanges();
}

public class MockReportContext : IReportContext
{
    IDbSet<Report> Reports {get;}

    public int SaveChanges()
    {
        //Need to detect changes here???
    }

    public MockReportContext()
    {
       Reports = new MockDbSet<Report>();
    }
}

public class MockDbSet<T> : IDbSet<T>
{
    readonly ObservableCollection<T> _data;
    readonly IQueryable _query;

    public FakeDbSet()
    {
        _data = new ObservableCollection<T>();
        _query = _data.AsQueryable();
    }

    public FakeDbSet(ObservableCollection<T> data)
    {
        _data = data;
        _query = _data.AsQueryable();
    }

    public virtual T Find(params object[] keyValues)
    {
        throw new NotImplementedException();
    }

    public T Add(T item)
    {
        _data.Add(item);
        return item;
    }

    public T Remove(T item)
    {
        _data.Remove(item);
        return item;
    }

    public T Attach(T item)
    {
        _data.Add(item);
        return item;
    }

    public T Detach(T item)
    {
        _data.Remove(item);
        return item;
    }

    public T Create()
    {
        return Activator.CreateInstance<T>();
    }

    public TDerivedEntity Create<TDerivedEntity>() where TDerivedEntity : class, T
    {
        return Activator.CreateInstance<TDerivedEntity>();
    }

    public ObservableCollection<T> Local
    {
        get { return _data; }
    }

    Type IQueryable.ElementType
    {
        get { return _query.ElementType; }
    }

    System.Linq.Expressions.Expression IQueryable.Expression
    {
        get { return _query.Expression; }
    }

    IQueryProvider IQueryable.Provider
    {
        get { return _query.Provider; }
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return _data.GetEnumerator();
    }

    IEnumerator<T> IEnumerable<T>.GetEnumerator()
    {
        return _data.GetEnumerator();
    }
}

Dies funktioniert gut zum Hinzufügen, Löschen und Abrufen von Entitäten.Wenn ich jedoch Folgendes versuche:

IReportContext context = new MockReportContext();
context.Reports.Add(new Report()); //Works
Report report = context.Reports.First(); //Works
report.Message = "Hello World!";
context.SaveChanges(); //Does nothing

Woher weiß der MockReportContext, dass sich das zurückgegebene Berichtsobjekt geändert hat??Ich weiß, dass die Verwendung von Entity Framework dies tut, also muss es möglich sein, aber ich habe keine Ahnung, wie...

War es hilfreich?

Lösung

Ich denke, du bist meistens da, aber ich würde vorschlagen, ein spöttisches Framework wie zu verwenden Moq (meine persönliche Präferenz) oder Nashorn verspottet um das zu verspotten IReportContext für Ihre Komponententests, anstatt sich die Mühe zu machen, eine zu erstellen Gefälschte klasse wie MockReportContext.(Okay, das Erlernen eines spöttischen Frameworks ist mit einigen Problemen verbunden, aber es wird später eine Menge falscher Klassenarbeit ersparen.)

Ich würde annehmen, dass Sie den Code, der von der Komponente abhängt, Unit-testen IReportContext, so dass Sie drinnen nichts tun müssen SaveChanges(), Sie müssen nur behaupten, dass Ihr Code aufgerufen hat SaveChanges() intern, wenn es sein sollte.

Hier ist ein guter Überblick der Verwendung von Moq mit den abgeleiteten DbContext / DbSet-Klassen von Entity Framework.

In der oben verlinkten Übersicht, wenn der Komponententest am Ende eine Methode testete, die intern aufruft SaveChanges(), es könnte zusätzlich verifizieren, dass SaveChanges() wurde in der Tat von Ihrer Methode mit der Zeile aufgerufen:

dc.Verify(db => db.SaveChanges());

Du könntest das auch mit deinem machen MockReportContext klasse durch Setzen einer Seiteneigenschaft auf True innerhalb der SaveChanges() klasse und Überprüfung am Ende Ihres Komponententests, aber ein spöttisches Framework ist viel flexibler und erspart das Schreiben zusätzlicher Klassen für Komponententests.

Wenn Sie die Verwendung eines spöttischen Frameworks vermeiden möchten, dann hier wie man es mit Fälschungen macht.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top