EntityFramework, DbContextScope und Effort - Ausnahme: DbContext wurde im Komponententest entfernt

c# dbcontext effort entity-framework unit-testing

Frage

Ich versuche Unit-Tests (mit NUnit) für Service-Layer zu schreiben, die Folgendes verwenden:

  1. Entity Framework als Datenzugriffsschicht
  2. DbContextScope zum Verwalten der DbContext-Lebensdauer

Ich verwende auch Effort.EF6, um DbContext in Unit Tests zu verspotten. Leider kann ich keinen Weg finden, DbContextScope kompatibel mit Effort zu machen, so dass ich alle Fälle korrekt testen kann.


Überblick über den Code

Service-Layer bestehen aus Klassen (Services), die eine gewisse Geschäftslogik haben. Jede Methode wird als vollständige Transaktion behandelt und mit context.SaveChanges() . Beispiel:

    private IDbContextScopeFactory _dbContextScopeFactory;

    public DepartmentsService(IDbContextScopeFactory dbContextScopeFactory)
    {
        _dbContextScopeFactory = dbContextScopeFactory;
    }

    public BusinessModel.Department Insert(BusinessModel.Department department)
    {
        using (var dbContextScope = _dbContextScopeFactory.Create())
        {
            // Validation
            ValidateAndThrowOnFailure(department, new DepartmentAddValidator());

            // Operation
            DBModel.Department newDepartment = Mapper.Map<DBModel.Department>(department);

            newDepartment.InsertDateUTC = DateTime.UtcNow;

            dbContextScope.DbContexts.Get<DPSContext>().Departments.Add(newDepartment);
            dbContextScope.SaveChanges();

            return Mapper.Map<BusinessModel.Department>(newDepartment);
        }
    }

Um diese Methode zu testen, mache ich einige Vorbereitungen vor jedem Test:

    private IDbContextScopeFactory _dbContextScopeFactory;

    public DepartmentsService(IDbContextScopeFactory dbContextScopeFactory)
    {
        _dbContextScopeFactory = dbContextScopeFactory;
    }

    public BusinessModel.Department Insert(BusinessModel.Department department)
    {
        using (var dbContextScope = _dbContextScopeFactory.Create())
        {
            // Validation
            ValidateAndThrowOnFailure(department, new DepartmentAddValidator());

            // Operation
            DBModel.Department newDepartment = Mapper.Map<DBModel.Department>(department);

            newDepartment.InsertDateUTC = DateTime.UtcNow;

            dbContextScope.DbContexts.Get<DPSContext>().Departments.Add(newDepartment);
            dbContextScope.SaveChanges();

            return Mapper.Map<BusinessModel.Department>(newDepartment);
        }
    }

Der Test und das Problem

Hier ist ein einfacher Komponententest:

    private IDbContextScopeFactory _dbContextScopeFactory;

    public DepartmentsService(IDbContextScopeFactory dbContextScopeFactory)
    {
        _dbContextScopeFactory = dbContextScopeFactory;
    }

    public BusinessModel.Department Insert(BusinessModel.Department department)
    {
        using (var dbContextScope = _dbContextScopeFactory.Create())
        {
            // Validation
            ValidateAndThrowOnFailure(department, new DepartmentAddValidator());

            // Operation
            DBModel.Department newDepartment = Mapper.Map<DBModel.Department>(department);

            newDepartment.InsertDateUTC = DateTime.UtcNow;

            dbContextScope.DbContexts.Get<DPSContext>().Departments.Add(newDepartment);
            dbContextScope.SaveChanges();

            return Mapper.Map<BusinessModel.Department>(newDepartment);
        }
    }

Das Problem ist, dass der Test mit Ausnahme fehlschlägt:

    private IDbContextScopeFactory _dbContextScopeFactory;

    public DepartmentsService(IDbContextScopeFactory dbContextScopeFactory)
    {
        _dbContextScopeFactory = dbContextScopeFactory;
    }

    public BusinessModel.Department Insert(BusinessModel.Department department)
    {
        using (var dbContextScope = _dbContextScopeFactory.Create())
        {
            // Validation
            ValidateAndThrowOnFailure(department, new DepartmentAddValidator());

            // Operation
            DBModel.Department newDepartment = Mapper.Map<DBModel.Department>(department);

            newDepartment.InsertDateUTC = DateTime.UtcNow;

            dbContextScope.DbContexts.Get<DPSContext>().Departments.Add(newDepartment);
            dbContextScope.SaveChanges();

            return Mapper.Map<BusinessModel.Department>(newDepartment);
        }
    }

Es scheint, dass DbContextScope, das innerhalb der Insert Methode verwendet wird, intern zugewiesene Kontexte am Ende des using Blocks zur Verfügung stellt und somit die Assert Ausnahme Assert wenn sie aufgerufen wird. Ist jemand auf ein ähnliches Problem gestoßen oder weiß ich, was ich tun soll, um dieses und ähnliche Szenarien erfolgreich zu testen?

Akzeptierte Antwort

Für jeden, der auf ein ähnliches Problem stößt, habe ich eine etwas schmutzige aber funktionierende Lösung geschaffen (zumindest hoffe ich es). Zusätzlich zu dem, was ich in der Frage geschrieben habe, habe ich eine Klasse erstellt, die vom realen Kontext abgeleitet ist und die Dispose Methode dazu gebracht hat, nichts zu tun. Ich habe auch eine RealDispose Methode hinzugefügt, die am Ende jedes Tests aufgerufen wird.

    public class TestableDPSContext : DBModel.DPSContext
    {
        public TestableDPSContext(DbConnection connection)
            : base(connection)
        {

        }

        protected override void Dispose(bool disposing)
        {
            // Do nothing
        }

        public void RealDispose(bool disposing)
        {
            // Invoke real dispose
            base.Dispose(disposing);
        }
    }

    [TearDown]
    public void FinishTest()
    {
        _dbEntities.RealDispose(false);
    }

Vielleicht gibt es eine bessere Lösung, aber im DbContext scheint es das Problem zu DbContext dass DbContext zu früh in Tests entsorgt wird.




Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum