C# 如何在不显式指定或使用重载的情况下对签名中具有可选参数的方法进行 Moq?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12957537/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I Moq a method that has an optional argument in its signature without explicitly specifying it or using an overload?
提问by Appulus
Given the following interface:
鉴于以下接口:
public interface IFoo
{
bool Foo(string a, bool b = false);
}
Attempting to mock it using Moq:
尝试使用 Moq 模拟它:
var mock = new Mock<IFoo>();
mock.Setup(mock => mock.Foo(It.IsAny<string>())).Returns(false);
gives the following error at compile time:
在编译时给出以下错误:
An expression tree may not contain a call or invocation that uses optional arguments
表达式树不能包含使用可选参数的调用或调用
I've found the issue above raised as an enhancementin Moq's list of issues and it appears to be assigned to the 4.5 release (whenever that is).
我发现上面的问题是作为Moq 问题列表中的增强功能提出的,它似乎已分配给 4.5 版本(无论何时)。
My question is: what should I do given that the above is not going to be fixed anytime soon? Are my options only to either explicitly set the default value of the optional parameter every time I mock it (which kind of defeats the point of specifying one in the first place) or to create an overload without the bool (like what I would have done prior to C# 4)?
我的问题是:鉴于上述问题不会很快得到解决,我该怎么办?我的选择是只在每次模拟时显式设置可选参数的默认值(这会破坏首先指定一个的点)还是创建没有 bool 的重载(就像我会做的那样)在 C# 之前 4)?
Or has anyone come across a more clever way to overcome this issue?
或者有没有人遇到过更聪明的方法来克服这个问题?
采纳答案by Chris Mantle
I believe your only choice right now is to explicitly include the boolparameter in the setup for Foo.
我相信您现在唯一的选择是bool在Foo.
I don't think it defeats the purpose of specifying a default value. The default value is a convenience for calling code, but I think that you should be explicit in your tests. Say you could leave out specifying the boolparameter. What happens if, in future, someone changes the default value of bto true? This will lead to failing tests (and rightfully so), but they will be more difficult to fix because of the hidden assumption that bis false. Explicitly specifying the boolparameter has another benefit: it improves the readability of your tests. Someone going through them will quickly know that there's one Foofunction that accepts two parameters. That's my 2 cents, at least :)
我不认为它违背了指定默认值的目的。默认值是调用代码的方便,但我认为你应该在你的测试中明确。假设您可以省略指定bool参数。如果将来有人更改bto的默认值会发生true什么?这将导致测试失败(这是理所当然的),但由于隐藏的假设b是false. 显式指定bool参数还有另一个好处:它提高了测试的可读性。看过它们的人很快就会知道有一个Foo函数接受两个参数。那是我的 2 美分,至少 :)
As for specifying it every time you mock it, don't duplicate code: create and/or initialise the mock in a function, so that you only have a single point of change. If you really want to, you can overcome Moq's apparent short-coming here by duplicating Foo's parameters into this initialisation function:
至于每次模拟时都指定它,不要重复代码:在函数中创建和/或初始化模拟,这样您就只有一个更改点。如果你真的想要,你可以通过将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
{
...
}
}
回答by Gil Grossman
Just encountered this issue today, Moq doesn't support this use case. So, seems that overriding the method would be sufficient for this case.
今天刚遇到这个问题,Moq 不支持这个用例。因此,对于这种情况,似乎覆盖该方法就足够了。
public interface IFoo
{
bool Foo(string a);
bool Foo(string a, bool b);
}
Now both methods are available and this example would work:
现在这两种方法都可用,这个例子可以工作:
var mock = new Mock<IFoo>();
mock.Setup(mock => mock.Foo(It.IsAny<string>())).Returns(false);
回答by CF5
Using Moq version 4.10.1 I have been able to do the following
使用 Moq 版本 4.10.1 我已经能够做到以下几点
With Interface:
带接口:
public interface IFoo
{
bool Foo(string a, bool b = false);
}
And Mock
和模拟
var mock = new Mock<IFoo>();
mock.Setup(mock => mock.Foo(It.IsAny<string>(), It.IsAny<bool>())).Returns(false);
Resolves a call to Foo with the first parameter okay
使用第一个参数可以解析对 Foo 的调用

