通过Setup设置mock属性会导致'Expression不是方法调用'

时间:2012-02-07 15:13:54

标签: c# .net mocking moq

我有以下代码,其中我的Mock接口有一个Recorder属性,它是一个类。

然后我尝试在该类上设置属性,但是出现Expression is not a method invocation错误。你能帮忙吗?

错误是在运行时尝试设置枚举属性。它使用以下堆栈跟踪抛出ArgumentException:

at Moq.ExpressionExtensions.ToMethodCall(LambdaExpression expression)
   at Moq.Mock.<>c__DisplayClass1c`2.<Setup>b__1b()
   at Moq.PexProtector.Invoke[T](Func`1 function)
   at Moq.Mock.Setup[T,TResult](Mock mock, Expression`1 expression, Func`1 condition)
   at Moq.Mock`1.Setup[TResult](Expression`1 expression)

由于

//Works
var mock = new Moq.Mock<IEngine>(); 
//Works
mock.Setup(x => x.Recorder).Returns(new Moq.Mock<Recorder>().Object);  
//Fails on the next line assigning a property value!!!
mock.Setup(x => x.Recorder.RunState).Returns(Recorder.eRunStates.Play);  

UPDATE - 我发现RunState不是属性,而是一个字段/成员,它是一个枚举

4 个答案:

答案 0 :(得分:8)

我发现创建Recorder的模拟然后将值赋给模拟对象似乎解决了这个问题。不确定这是否是正确的做事方式。

var mockRecorder = new Moq.Mock<Recorder>();
mockRecorder.Object.RunState = Recorder.eRunStates.Play;

答案 1 :(得分:4)

我认为你应该返回你在第一部分为第二部分创建的模拟:

var mockRecorder = new Moq.Mock<Recorder>();
mock.Setup(x => x.Recorder).Returns(mockRecorder.Object);
mockRecorder.Setup(x => x.RunState).Returns(Recorder.eRunStates.Play);

这只是一个猜测,没有自己使用Moq - 但它是有道理的。

然而,这看起来最终会变得相当脆弱。你可能想考虑在这里使用假的 - 至少一个的对象,如果不是两者的话。

编辑:看documentation,另一种选择是:

// Moq will set up the hierarchy for you...
mock.Setup(x => x.Recorder.RunState).Returns(Recorder.eRunStates.Play);

答案 2 :(得分:2)

如果您在模拟上使用SetupGet而不是设置,则可以使用

var mockRecorder = new Moq.Mock<Recorder>();
mock.SetupGet(x => x.Recorder).Returns(mockRecorder.Object);
mockRecorder.SetupGet(x => x.RunState).Returns(Recorder.eRunStates.Play);

答案 3 :(得分:1)

您需要在Mock对象上进行设置,以改为配置RunState属性。

var mockRecorder = new Mock<Recorder>();
mockRecorder.Setup(x => x.RunState).Returns(eRunStates.Play);

mock.Setup(x => x.Recorder).Returns(mockRecorder.Object);

编辑:仅供参考,您需要在访问.Object属性之前对模拟执行所有设置,因为此时创建了对象,并且无法进行进一步的设置。

另外,一些建议,看起来你的运行状态的枚举嵌套在你的录音机类中,我会把它移到一个单独的类&amp;另外删除'e'前缀。