Универсальный репозиторий не добавляет сущность в контекст при тестировании

Я создаю GenericRepository с EF и пишу модульные тесты впервые. Тесты для GetAll() а также Update() прошло но Add() а также Delete() не удалось. Почему не Add? Я вырываю свои волосы, потому что это одна строка кода, и я не мог понять это. Я использую базу данных EF First, Nunit, Nsubstitute.

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

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
    }

1 ответ

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

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

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

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

Другие вопросы по тегам