我用EF创建GenericRepository并首次编写单元测试。 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
}
答案 0 :(得分: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()并使用实际的List。