2016-03-30 3 views
1

Я создаю GenericRepository с EF и записываю Unit Tests в первый раз. Испытания на GetAll() и Update() прошли, но Add() и Delete() не удалось. Почему это не Add? Я вытаскиваю волосы, потому что это одна строка кода, и я не мог понять. Я использую базу данных EF Во-первых, Nunit, Nsubstitute.Generic Repository не добавляет сущность в контекст при тестировании

Любые советы приветствуются.

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; } 

Тесты

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

Соответствует ли ваш тип '' Customer 'соответствующему типу объекта? –

+0

Я не включил все свойства в 'Customer'. Некоторые из полей не могут быть пустыми. Но 'repo.Save()' не выбрасывал исключение. – Firefly

+0

Извините, для уточнения типа 'Customer' ДОЛЖЕН быть тот же тип, который сопоставляется с таблицей в структуре сущности. Как вы определили свой контекст? Вы используете Database-First или Code-First? –

ответ

0

Вы определяете переменные данные здесь IQueryable сразу и использовать его для имитации _dbSet в вашем хранилище.

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

Так что, когда вы делаете .Add() вы на самом деле добавление к IQueryable, который является интерфейс только для чтения.

Избавиться от AsQueryable() из определения данных и использовать фактический список.

+0

Это, кажется, проблема. 'mockSet' возвращается как' IQueryable '. Но мне нужно «IQueryable», чтобы издеваться над Dbset. Вы знаете, как вернуть 'mockSet' в список? – Firefly

+0

Я не знаком с NSubstitute, но когда я использую Moq для своих модульных тестов, мне пришлось реализовать методы 'Add()' и 'Remove()' для работы с IDbSet. Посмотрите на два метода .Setup() здесь: [link] (https://dotnetfiddle.net/6IJHty) Возможно, вам придется делать то же самое в своей насмешличной структуре. –

 Смежные вопросы

  • Нет связанных вопросов^_^