我好几天都陷入了一个非常奇怪的问题,无法找到解决方案。我正在嘲笑DatabaseContext
和一些DBSet<T>
实体。创建moq工作正常,看起来很好。
在特殊.Any()
上调用DBSet
时,它会与NullReferenceException
崩溃。我仔细看了一下,发现我的模拟DBSet
的表达式和提供者再次为空。但我不明白为什么。
创建DB-Set的函数:
private DbSet<T> GetQueryableMockDbSet<T>() where T : class
{
var list = mockListCollection.Single(o => o.GetType().GetGenericArguments()[0] == typeof (T))
.ToList()
.ConvertAll(o => (T) o);
var queryable = list.AsQueryable();
var dbSet = new Mock<DbSet<T>>();
dbSet.As<IQueryable<T>>()
.Setup(m => m.Provider)
.Returns(new TestDbAsyncQueryProvider<T>(queryable.Provider));
//dbSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(queryable.Provider);
dbSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(queryable.Expression);
dbSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(queryable.ElementType);
dbSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(() => queryable.GetEnumerator());
dbSet.Setup(d => d.Add(It.IsAny<T>())).Callback<T>(list.Add);
dbSet.Object.AddRange(list);
return dbSet.Object;
}
我的DatabaseContext
:
private void InitMockMethods<T>() where T : class, new()
{
this.DataBaseContextMock.Setup(m => m.Set<T>()).Returns(this.GetQueryableMockDbSet<T>());
this.DataBaseContextMock.Setup(m => m.Set<T>().Local).Returns(new ObservableCollection<T>(this.GetQueryableMockDbSet<T>()));
this.DataBaseContextMock.Setup(m => m.Set<T>().Create()).Returns(new T());
// first get the parameter name out of database context by generic type argument (e. g. DbSet<TblProject> --> get name by TblProject)
// because type and typename are not equal.
// TblProject --> Name is TblProjects
var paramName = typeof (IDatabaseContext).GetProperties().Single(o => o.CanWrite && o.PropertyType.GetGenericArguments()[0] == typeof(T)).Name;
// build lamda expression for moq setup
var parameter = Expression.Parameter(typeof(IDatabaseContext));
var body = Expression.PropertyOrField(parameter, paramName);
var lambdaExpression = Expression.Lambda<Func<IDatabaseContext, object>>(body, parameter);
// setup moq
this.DataBaseContextMock.Setup(lambdaExpression).Returns((DbSet<T>)this.GetQueryableMockDbSet<T>());
}
之后,所有对象看起来都很好。但是当我调用DatabaseContext.Set<TblVendor>().Any()
时,它会因为Provider和Expression为空而崩溃。
有人在那里,谁知道,哪些可能是错的?!
编辑: 这是测试功能:
[Test]
[TestCase(11,31)]
public void TestFilterExtension(int expGl1, int expGl2)
{
var userMock = new Mock<AspNetUser>();
userMock.Setup(x => x.EnableFilterByUserAuthorization).Returns(true);
userMock.Setup(x => x.Tablename).Returns("TblVendor");
userMock.Setup(x => x.Columnname).Returns("gl");
userMock.Setup(x => x.Value).Returns(expGl1.ToString);
var gl = new Mock<TblVendor>();
gl.Setup(n => n.Id).Returns(Guid.NewGuid);
gl.Setup(x => x.GL).Returns(expGl1);
var gl2 = new Mock<TblVendor>();
gl2.Setup(n => n.Id).Returns(Guid.NewGuid);
gl2.Setup(x => x.GL).Returns(expGl2);
var manager = new VendorManager(base.Manager, MockProvider.Instance.DataBaseContextMock.Object,
userMock.Object, MockProvider.Instance.EntityHelperMock.Object);
//MockProvider.Instance.ClearMockList<TblVendor>();
//manager.AddOrUpdate(gl.Object);
//manager.AddOrUpdate(gl2.Object);
var test = MockProvider.Instance.DataBaseContextMock.Object.Set<TblVendor>();
var b = test.Any(); // <----- NullReferenceException because of missing Provider and or Expression
//var b = manager.EntityCollection;
//var data = manager.EntityCollection.ToList();
}
答案 0 :(得分:0)
我发现你已经使用了异步提供程序方式,所以我会告诉你尝试实现getenumerator异步,如msdn指南中所述,如何模拟ef dbcontext。
完成后,请避免使用moq查询,因为不需要。您的模拟已经按预期使用linq查询!此外,如果有另一个函数调用为Include(),你必须模拟它以返回你想要的itrm(大多数时候将是原始对象mock,原始列表)