2013-05-08 174 views
0

我试图用莫克嘲笑IDataRecord如何模拟IDataRecord?

的模拟被创建为如下:

Mock<IDataRecord> mockDataRecord = new Mock<IDataRecord>(); 

下测试该生产线是:

DateTime timestamp = dataRecord.GetValueOrDefault<DateTime>("QUEUE_ADD_TS"); 

曾尝试:

mockDataRecord.Setup(r => r.GetValueOrDefault<DateTime>("QUEUE_ADD_TS")).Returns(now); 

...但它给出了一个运行时错误:

Expression references a method that does not belong to the mocked object: r => r.GetValueOrDefault("QUEUE_ADD_TS")

也尝试用It.IsAny<String>()代替"QUEUE_ADD_TS",但它没有区别。这应该很容易,但我正在挠头 - 感谢任何建议!

+2

我看到了'IDataRecord'接口上没有'GetValueOrDefault '方法。它不是扩展方法吗? – 2013-05-08 08:14:17

+1

很确定它就像错误提示一样。 GetValueOrDefault是一个扩展方法,所以不能直接存根。尝试改变索引器的存根,我确定例子会在某处:) – gaz 2013-05-08 08:14:25

+0

啊,你们都是对的!结果'GetValueOrDefault'是一个扩展方法,并且是'static',所以不容易被模拟。不知道如何工作,但看着它... – 2013-05-08 08:23:16

回答

0

你不能嘲笑静态或扩展方法,因为大多数模拟框架都使用动态代理。

在你的测试中,不要存根扩展方法。相反,存根原来的方法本身,如:

mockDataRecord.Setup(r => r.GetValue<DateTime>("QUEUE_ADD_TS")).Returns(now); 

您应该单独测试的扩展方法,如:

  1. 存根GetValue方法,并声称GetValueOrDefault返回存根值。

  2. Donot stub GetValue方法,并声明GetValueOrDefault返回默认值。

+0

这确实是我现在正在做的 - 实际上没有遇到过扩展方法! (我不知道,你离开C#几年后回来,门柱已经移动;-))。我唯一的问题是有很多安装方法,并且StackOverflow上的一致意见是每个Setup()应该与一个等效的Verify()匹配。看起来有点过分,并会使代码更难以维护 - 我真的需要这样做,还是可以用Verifiable()来代替? – 2013-05-08 09:00:47

+0

VerifyAll()似乎比每个Setup()与Verify()配对要好。显然,这应该根据个案情况进行。你会是这个最好的评判者:-) – aquaraga 2013-05-08 09:08:48

+0

我已经完成了所谓的abve,就像这样:this.dataRecord.Setup(d => d.GetValue(“WorkItemId”))。但我得到的对象refference没有设置为对象的实例....我做错了什么?似乎我在评论中有同样的地方。 – 2015-03-16 08:22:10

0

我不喜欢这样,快速和肮脏的:

Mock<IDataRecord> dataRecord = new Mock<IDataRecord>(); 
Setup(column => column["applicationno"]).Returns("foobar"); 
Setup(column => column["numberOfApplications"]).Returns(12);