我正在尝试对以下代码行进行单元测试:
myDbContext.myDbSet.Load()
myObservableCollection = myDbContext.myDbSet.Local
我的测试方法如下:
Dim dataMyDbSet = New List(Of myDbSet) From {
new myDbSet() With{.Id=1},
new myDbSet() With{.Id=1},
new myDbSet() With{.Id=1}
}.AsQueryable()
Dim myDbSetMock = New Mock(Of DbSet(of myDbSet))
myDbSetMock.As(of IQueryable (Of myDbSet)).Setup(Function(m) m.Provider).Returns(dataMyDbSet.Provider)
myDbSetMock.As(of IQueryable (Of myDbSet)).Setup(Function(m) m.Expression).Returns(dataMyDbSet.Expression)
myDbSetMock.As(of IQueryable (Of myDbSet)).Setup(Function(m) m.ElementType).Returns(dataMyDbSet.ElementType)
myDbSetMock.As(of IQueryable (Of myDbSet)).Setup(Function(m) m.GetEnumerator).Returns(dataMyDbSet.GetEnumerator)
myDbSetMock.Setup(Function(x) x.Local).Returns(New ObservableCollection(Of myDbSet)(dataMyDbSet))
Dim MyDbContextMock = New Mock(of dbCrashtestNcap)
MyDbContextMock.Setup(function (f) f.myDbSet).Returns(myDbSetMock.Object)
Dim crashService = New CrashService(MyDbContextMock.Object)
Dim result = crashService.GetOcNcapKlassen()
Assert.That(result.Count,[Is].EqualTo(3))
这使我在第一行使用myDbContext.myDbSet.Load()获得NullReferenceException
我所有尝试模拟Load()或为myDbContext.myDbSet返回值(从而使NullPointerException
不存在)的尝试均失败了
一个可行的解决方法是更改ToList()中的Load(),但我希望保留Load()或至少了解是否有解决方案。在此先感谢您的帮助。解决方案可能是C#或vb.net,这对我来说并不重要
答案 0 :(得分:1)
您已经成功为Local
设置了模拟,它是DbSet<T>
类型的一个属性,您也已经对其进行了模拟。 Load
方法是静态方法(我相信它甚至是扩展方法,但在这种情况下都没有关系)。 Moq等框架使用代理技术来为不同类型的对象设置模拟。尽管这是一个不错的解决方案,但是它禁止您模拟virtual
或abstract
类型以外的任何内容,因此您不能使用Moq来开箱即用地模拟静态Load
方法。
您可以做的是在单元内部创建一个新方法,将其标记为virtual
,然后在其中调用Load
方法:
public class Unit
{
public void YourMethod()
{
// .. do stuff
CallStaticMethod(/* maybe pass parameters? */);
// .. do more stuff
}
public virtual void CallStaticMethod()
{
// call static method
Console.WriteLine("This is a static method call!");
}
}
public class UnitUnderTest : Unit
{
public override void CallStaticMethod()
{
// do whatever you want during testing only
// possibly call base.CallStaticMethod() to execute base method.
}
}
现在在单元测试中,您需要使用UnitUnderTest
并修改该类以使其符合您的需求。
答案 1 :(得分:1)
正如Ivan Stoev的评论中所述(再次感谢!),我的问题是Load()
不能在IQueryable的通用版本上运行,而不能在非通用版本上运行。因此,为解决此问题,我用以下内容替换了上面的四行,并且可以正常工作:
myDbSetMock.As(of IQueryable).Setup(Function(m) m.Provider).Returns(dataMyDbSet.Provider)
myDbSetMock.As(of IQueryable).Setup(Function(m) m.Expression).Returns(dataMyDbSet.Expression)
myDbSetMock.As(of IQueryable).Setup(Function(m) m.ElementType).Returns(dataMyDbSet.ElementType)
myDbSetMock.As(of IQueryable).Setup(Function(m) m.GetEnumerator).Returns(dataMyDbSet.GetEnumerator)
但是,如果要使用ToList(),则需要通用版本。