我不是通过创建和填充新的DbSet(Of TEntity) 来做到这一点的,正如这个问答标题所假设的,而是通过模拟DbSet(Of TEntity):
<Extension>
Public Sub Setup(Of TEntity As Class)(Instance As Mock(Of Db.Context), Entities As List(Of TEntity), ContextSetup As Expression(Of Func(Of Db.Context, DbSet(Of TEntity))))
Dim oDbSetReturn As Func(Of DbSet(Of TEntity))
Dim oDbSetSetup As Expression(Of Func(Of Db.Context, DbSet(Of TEntity)))
Dim oDbSetMock As Mock(Of DbSet(Of TEntity))
Dim oDbSet As DbSet(Of TEntity)
oDbSetMock = New Mock(Of DbSet(Of TEntity))
oDbSetMock.Setup(Entities)
oDbSet = oDbSetMock.Object
oDbSetReturn = Function() oDbSet
oDbSetSetup = Function(Context) Context.Set(Of TEntity)
Instance.Setup(ContextSetup).Returns(oDbSet)
Instance.Setup(oDbSetSetup).Returns(oDbSetReturn)
End Sub
这是 DbSet(Of TEntity) 设置的配套方法:
<Extension>
Public Sub Setup(Of TEntity As Class)(Instance As Mock(Of DbSet(Of TEntity)), Entities As List(Of TEntity))
Dim oRemoveRangeReturn As Func(Of IEnumerable(Of TEntity), IEnumerable(Of TEntity))
Dim oRemoveRangeSetup As Expression(Of Func(Of DbSet(Of TEntity), IEnumerable(Of TEntity)))
Dim oAddRangeReturn As Func(Of IEnumerable(Of TEntity), IEnumerable(Of TEntity))
Dim oAddRangeSetup As Expression(Of Func(Of DbSet(Of TEntity), IEnumerable(Of TEntity)))
Dim oRemoveReturn As Func(Of TEntity, TEntity)
Dim oRemoveSetup As Expression(Of Func(Of DbSet(Of TEntity), TEntity))
Dim oAddReturn As Func(Of TEntity, TEntity)
Dim oAddSetup As Expression(Of Func(Of DbSet(Of TEntity), TEntity))
Instance.As(Of IQueryable(Of TEntity)).Setup(Function(Queryable) Queryable.GetEnumerator).Returns(Entities.AsQueryable.GetEnumerator)
Instance.As(Of IQueryable(Of TEntity)).Setup(Function(Queryable) Queryable.ElementType).Returns(Entities.AsQueryable.ElementType)
Instance.As(Of IQueryable(Of TEntity)).Setup(Function(Queryable) Queryable.Expression).Returns(Entities.AsQueryable.Expression)
Instance.As(Of IQueryable(Of TEntity)).Setup(Function(Queryable) Queryable.Provider).Returns(Entities.AsQueryable.Provider)
oRemoveRangeSetup = Function(DbSet) DbSet.RemoveRange(It.IsAny(Of IEnumerable(Of TEntity)))
oAddRangeSetup = Function(DbSet) DbSet.AddRange(It.IsAny(Of IEnumerable(Of TEntity)))
oRemoveSetup = Function(DbSet) DbSet.Remove(It.IsAny(Of TEntity))
oAddSetup = Function(DbSet) DbSet.Add(It.IsAny(Of TEntity))
oRemoveRangeReturn = Function(Range)
Entities = Entities.Except(Range)
Return Entities
End Function
oAddRangeReturn = Function(Range)
Entities.AddRange(Range)
Return Entities
End Function
oRemoveReturn = Function(Entity)
Entities.Remove(Entity)
Return Entity
End Function
oAddReturn = Function(Entity)
Entities.Add(Entity)
Return Entity
End Function
Instance.Setup(oRemoveRangeSetup).Returns(oRemoveRangeReturn)
Instance.Setup(oAddRangeSetup).Returns(oAddRangeReturn)
Instance.Setup(oRemoveSetup).Returns(oRemoveReturn)
Instance.Setup(oAddSetup).Returns(oAddReturn)
End Sub
它是这样称呼的:
Private ReadOnly Property DbContextFactory As Func(Of Db.Context)
Get
Dim oContextMock As Mock(Of Db.Context)
Return Function()
oContextMock = New Mock(Of Db.Context)
oContextMock.Setup(Of Db.City)(Me.Cities, Function(Context) Context.Cities)
oContextMock.Setup(Of Db.Role)(Me.Roles, Function(Context) Context.Roles)
oContextMock.Setup(Of Db.User)(Me.Users, Function(Context) Context.Users)
Return oContextMock.Object
End Function
End Get
End Property
这应该可行。我目前无法测试它,但我会尽快测试并提供结果。
--编辑 1--
我在Instance.Setup(ContextSetup) 收到“不支持的表达式”错误。为此,我在 Moq repo 上 opened a ticket。
--编辑 2--
再一次,stakx 来救援。
解决方案在铸件中找到。大多数模型需要DbSet(Of T),而两个身份派生模型(Db.Role 和Db.User)需要IDbSet(Of T)。
这会导致一对重载的扩展方法:
<Extension>
Public Sub Setup(Of TEntity As Class)(
Instance As Mock(Of Db.Context),
Entities As List(Of TEntity),
DbSetSetup As Expression(Of Func(Of Db.Context, IDbSet(Of TEntity)))
)
Instance.Setup(DbSetSetup).Returns(DbSet(Entities))
Instance.Setup(MethodSetup(Of TEntity)).Returns(MethodReturn(Entities))
End Sub
<Extension>
Public Sub Setup(Of TEntity As Class)(
Instance As Mock(Of Db.Context),
Entities As List(Of TEntity),
DbSetSetup As Expression(Of Func(Of Db.Context, DbSet(Of TEntity)))
)
Instance.Setup(DbSetSetup).Returns(DbSet(Entities))
Instance.Setup(MethodSetup(Of TEntity)).Returns(MethodReturn(Entities))
End Sub
Private Function MethodSetup(Of TEntity As Class)() As Expression(Of Func(Of Db.Context, DbSet(Of TEntity)))
Return Function(Context) Context.Set(Of TEntity)
End Function
Private Function MethodReturn(Of TEntity As Class)(Entities As List(Of TEntity)) As Func(Of DbSet(Of TEntity))
Return Function() DbSet(Entities)
End Function
Private Function DbSet(Of TEntity As Class)(Entities As List(Of TEntity)) As DbSet(Of TEntity)
With New Mock(Of DbSet(Of TEntity))
.Setup(Entities)
Return .Object
End With
End Function
最后这一切都奏效了。
谢谢stakx。