2016-03-30 13 views
1

Ich erstelle ein GenericRepository mit EF und schreibe Unit Tests zum ersten Mal. Tests für GetAll() und Update() bestanden, aber Add() und Delete() fehlgeschlagen. Warum ist es nicht Add? Ich ziehe mir die Haare aus, weil es eine Codezeile ist und ich es nicht herausfinden konnte. Ich benutze EF Datenbank zuerst, Nunit, Nsubstitute.Generisches Repository fügt keine Entität zum Kontext beim Testen hinzu

Jeder Rat ist willkommen.

public class GenericDataRepository<T, C> : IGenericDataRepository<T, C> where T : class where C : DbContext, new() { 

    protected C _context; 
    protected IDbSet<T> _dbSet; 

    public GenericDataRepository() { 
     _context = new C(); 
     _dbSet = _context.Set<T>(); 
    } 

    public GenericDataRepository(C context) { 
     _context = context; 
     _dbSet = context.Set<T>(); 
    } 

    public virtual IQueryable<T> GetAll() { 
     return _dbSet.AsQueryable<T>(); 
    } 

    public virtual T Add(T entity) { 
     return _dbSet.Add(entity); 
    } 

    public virtual void Update(T entity) { 
     _context.Entry(entity).State = EntityState.Modified; 
    } 

    public virtual T Delete(T entity) { 
     return _dbSet.Remove(entity); 
    } 

    public virtual void Save() { 
     _context.SaveChanges(); 
    } 

} 

MyEntities

public partial class MyEntities : DbContext{ 
public MyEntities() 
    : base("name=MyEntities") 
{ 
} 

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    throw new UnintentionalCodeFirstException(); 
} 

public virtual DbSet<Customer> Cusotmers{ get; set; } 

Tests

public static class NSubstituteUtils { 
    public static DbSet<T> CreateMockDbSet<T>(IQueryable<T> data = null) 
     where T : class { 
     var mockSet = Substitute.For<DbSet<T>, IQueryable<T>>(); 
     mockSet.AsNoTracking().Returns(mockSet); 

     if (data != null) { 
      var queryable = data.AsQueryable(); 

      // setup all IQueryable methods using what you have from "data" 
      ((IQueryable<T>)mockSet).Provider.Returns(data.Provider); 
      ((IQueryable<T>)mockSet).Expression.Returns(data.Expression); 
      ((IQueryable<T>)mockSet).ElementType.Returns(data.ElementType); 
      ((IQueryable<T>)mockSet).GetEnumerator().Returns(data.GetEnumerator()); 
     } 

     return mockSet; 
    } 
} 

static IQueryable<Customer> data; 
[SetUp] 
    public void Init() { 
     data = new List<Customer> { 
      new Customer { 
       CUSTOMER = "333", 
       CUSTOMERNAME = "no name" 
      }, 
      new Customer { 
       CUSTOMER = "555", 
       CUSTOMERNAME = "test name" 
      } 
     }.AsQueryable(); 
    } 
[Test] 
    public void Add_Should_AddGenericT() { 

     var mockSet = NSubstituteUtils.CreateMockDbSet<Customer>(data); 
     var mockContext = Substitute.For<MyEntities>(); 
     mockContext.Set<Customer>().Returns(mockSet); 

     var repo = new GenericDataRepository<Customer, MyEntities>(mockContext); 

     var customer = new Customer { 
      CUSTOMER1 = "123", 
      CUSTOMERNAME = "test name" 
     }; 
     var result = repo.Add(customer);  // issue here: result returns null which should be a Customer 
     repo.Save(); 

     var customerList = repo.GetAll().ToList(); 
     Assert.AreEqual(3, customerList.Count); // failed. Expected 3 but was 2 
    } 
+0

Passt Ihr 'Customer'-Typ zum entsprechenden Entitätstyp? –

+0

Ich habe nicht alle Eigenschaften in "Kunde" aufgenommen. Einige der Felder können nicht null sein. Aber 'repo.Save()' hat keine Ausnahme ausgelöst. – Firefly

+0

Sorry, um zu verdeutlichen, muss der 'Customer'-Typ derselbe Typ sein, der im Entity-Framework einer Tabelle zugeordnet ist. Wie haben Sie Ihren Kontext abgebildet? Verwenden Sie Database-First oder Code-First? –

Antwort

0

Sie sofort hier als IQueryable Datenvariable zu definieren und es mit dem _dbSet in Ihrem Repository zu verspotten.

data = new List<Customer> { 
     new Customer { 
      CUSTOMER = "333", 
      CUSTOMERNAME = "no name" 
     }, 
     new Customer { 
      CUSTOMER = "555", 
      CUSTOMERNAME = "test name" 
     } 
    }.AsQueryable(); 

Also, wenn Sie tun eine .Add() Sie hinzufügen tatsächlich zu einem IQueryable, die eine schreibgeschützte Schnittstelle ist.

Entfernen Sie AsQueryable() aus der Datendefinition und verwenden Sie die tatsächliche Liste.

+0

Das scheint das Problem zu sein. 'mockSet' kehrt als' IQueryable 'zurück. Aber ich brauche 'IQueryable', um das Dbset zu verspotten. Weißt du zufällig, wie man 'mockSet' als Liste zurückgibt? – Firefly

+0

Ich bin nicht vertraut mit NSsubstitute, aber wenn ich Moq für meine Unit-Tests verwende und ich musste sowohl die 'Add()' und 'Remove()' Methoden implementieren, um auf dem IDbSet zu arbeiten. Schauen Sie sich die beiden .Setup() Methoden hier an: [link] (https://dotnetfiddle.net/6IJHty) Sie müssen das gleiche in Ihrem spöttischen Rahmen tun. –

Verwandte Themen