正如标题所说,我遵循模型优先方法。所以我的模型类是自动生成的。如果我想模拟 DBContext
派生MyModelContainer
其中包含 DBSets
实体类。阅读一些内容,为了进行单元测试,您需要将其更改为 IDBSet
。是否可以做到这一点,特别是在我执行“运行自定义工具”时自动生成的类中,这是一个问题。但到目前为止我已经修改了它。
但真正的问题是:当我尝试 stub MyModelContainer
时返回从 IDBSet
生成的模拟。 Rhino 模拟正在引发 InvalidOperationException:“无效调用,已使用最后一次调用,或未进行任何调用(确保您正在调用虚拟(C#)/Overridable(VB)方法。”
这是我的单元测试代码。
MyModelContainer dbMock = MockRepository.GenerateMock<MyModelContainer>();
IDBSet<Models.MyEntity> entityMock = MockRepository.GenerateMock<IDBSet<Models.MyEntity>>()
dbMock.Stub( x=>x.MyEntities ).Return( entityMock );
最后一条语句触发了异常。我尝试使用 IDBSet<>
的假实现指定here ,但运气不佳!
我使用MVC 4,Rhino Mocks 3.6。任何帮助将不胜感激。
更新:
经过一些试验和研究,我找到了解决办法。我将代码更改为:
MyModelContainer dbMock = MockRepository.GenerateMock<MyModelContainer>();
IDBSet<Models.MyEntity> entityMock = MockRepository.GenerateMock<IDBSet<Models.MyEntity>>()
//dbMock.Stub( x=>x.MyEntities ).Return( entityMock );
dbMock.MyEntities = entityMock;
现在是InvalidOperationException
离开了。
测试失败仅由于 ExpectationViolationException
这应该是正常的。
对于自动生成的Model类,发现编辑DbContext's
T4 模板(.tt 扩展名) 就可以了。感谢Alan's Blog
但是我想知道为什么之前的代码不起作用。有人吗?
最佳答案
这里可能有两个原因:
MyEntites
MyModelContainer
的属性(property)不是虚拟的。
在这种情况下,Rhino Mock 根本无法 stub 该属性。然后dbMock.Stub(x=>x.MyEntities)
将会失败。MyEntites
属性是虚拟的,但同时具有公共(public) getter 和公共(public) setter。
然后记号dbMock.Stub(x=>x.MyEntities).Return(entityMock)
不允许。您可以看到解释,例如here .
在这两种情况下,正确的修复方法正是您所做的:使用 dbMock.MyEntities = entityMock
而不是dbMock.Stub(x=>x.MyEntities).Return(entityMock)
.
关于unit-testing - 模拟 DBSet,EF 模型优先,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15516543/