如何Moq一个方法,在其签名中有一个可选的参数,没有明确指定或使用重载?

鉴于以下界面:

public interface IFoo { bool Foo(string a, bool b = false); } 

试图用Moq来嘲笑它:

 var mock = new Mock<IFoo>(); mock.Setup(mock => mock.Foo(It.IsAny<string>())).Returns(false); 

在编译时给出以下错误:

expression式树可能不包含使用可选参数的调用或调用

我发现上面提到的问题是Moq问题清单中的一个增强 ,它似乎被分配到4.5版本(无论何时)。

我的问题是:我应该怎么做才能使上述问题不会很快得到解决呢? 我的select只是要么显式设置可选参数的默认值每次我嘲笑它(哪种破坏首先指定一个点)或创build一个没有bool的重载(就像我会做的在C#4之前)?

还是有人遇到更聪明的方法来解决这个问题?

我相信你现在唯一的select是在Foo的设置中明确包含bool参数。

我不认为它违背了指定默认值的目的。 默认值是调用代码的一个方便,但我认为你应该在你的testing中明确。 假设你可以不指定bool参数。 如果将来有人将b的默认值更改为true ,会发生什么情况? 这会导致testing失败(并且正确如此),但是由于隐藏的假设bfalse ,所以它们将更难以修复。 明确指定bool参数还有另一个好处:它提高了testing的可读性。 有人通过他们会很快知道有一个Foo函数接受两个参数。 这是我的2美分,至less:)

至于每当你嘲笑它时都指定它,不要复制代码:在一个函数中创build和/或初始化模拟,这样你只有一个改变点。 如果你真的想要的话,你可以通过将Foo的参数复制到这个初始化函数中来克服Moq显然的短缺:

 public void InitFooFuncOnFooMock(Mock<IFoo> fooMock, string a, bool b = false) { if(!b) { fooMock.Setup(mock => mock.Foo(a, b)).Returns(false); } else { ... } } 

刚才遇到这个问题,Moq不支持这个用例。 所以,似乎凌驾于这种情况下的方法就足够了。

 public interface IFoo { bool Foo(string a); bool Foo(string a, bool b); } 

现在这两个方法都可用,这个例子可以工作:

 var mock = new Mock<IFoo>(); mock.Setup(mock => mock.Foo(It.IsAny<string>())).Returns(false);