在VS15中使用Moq进行单元测试时,returnsasync(null)会产生构建错误

Jus*_*meo 19 c# unit-testing asynchronous moq

当我ReturnsAsync(null)在Visual Studio(with Moq)中使用C#单元测试方法时,我收到错误:

"以下方法或属性之间的调用不明确"

然后是ReturnsAsync具有不同参数的方法列表.我知道这是由于ReturnsAsync函数被重载.但是,当我在同事的计算机上运行相同的单元测试时,它运行没有任何错误.有谁知道为什么会这样?有谁知道如何解决这一问题?

此外,当我建立时,我收到警告:

所有引用********的软件包都必须安装nuget软件包Microsoft.Bcl.Build.

这会有什么影响吗?

Ser*_*kiy 34

ReturnsAsyncMoq类有两种扩展方法ReturnsExtensions.它们有以下参数:

(this IReturns<TMock, Task<TResult>> mock, TResult value)
(this IReturns<TMock, Task<TResult>> mock, Func<TResult> valueFunction)
Run Code Online (Sandbox Code Playgroud)

正如您所看到的那样,一个接受应该由task返回的值,而另一个接受将返回值的委托.当你传递null编译器时,不知道它是值还是委托.当task参数是值类型(例如int)时,情况并非如此.因为它不能为null并且编译器理解null是委托.你的同事的电脑可能就是这种情况.

要修复此错误,您需要帮助编译器选择正确的方法重载 - 将null转换为任务结果的类型(例如字符串):

RetursAsync((string)null)
Run Code Online (Sandbox Code Playgroud)

或者您可以传递null值

string s = null;
... ReturnsAsync(s);
Run Code Online (Sandbox Code Playgroud)

  • 或者,如果升级后有很多这些错误,并且不想打算转换为不同的返回类型:`ReturAsync(()=> null)` (16认同)
  • 或者你可以通过`RetursAsync(default(string))` (3认同)

Daw*_*žan 16

问题在于编译器根据方法参数的类型和传递的参数类型来选择要调用的重载方法。这称为方法重载解析。但字面null意思是“没有值”,同时,它本身不携带任何类型信息。如果没有类型,编译器不知道要调用哪个重载方法,因此它会抱怨“调用不明确”。

\n

如果您传递文字"Hello world"而不是null,您(编译器)就知道它有一个值(文本“Hello world”)并且它是类型string。但在 的情况下null,类型信息丢失 \xe2\x80\x93 它可能是没有值的字符串,没有值的委托,或者例如没有值的自定义引用类型。

\n

正如Sergey 提到的,有两种重载方法:

\n
(this IReturns<TMock, Task<TResult>> mock, TResult value)\n(this IReturns<TMock, Task<TResult>> mock, Func<TResult> valueFunction)\n
Run Code Online (Sandbox Code Playgroud)\n

它们都有一个参数,第一个参数为 type TResult,第二个参数为 type Func<TResult>。没有null类型信息的可能是它们两者/任何一个,所以你只需要提示编译器调用哪一个。

\n

您有两个选择:

\n
    \n
  • 将值链接null到某种类型并调用重载接受TResult
  • \n
  • 传递一个返回的函数null,即调用重载接受Func<TResult>
  • \n
\n

对我来说,最简单的解决方案是将其包装null到一个函数中,这样我就不必再担心类型了。我只是传递了一个作为参数返回的lambda 表达式,这意味着我使用了第二个接受委托的重载方法:nullFunc<TResult>

\n
ReturnAsync(() => null)\n
Run Code Online (Sandbox Code Playgroud)\n

另一方面,正如 Sergey 提到的,您可以将 分配null给类型变量并传递:

\n
string x = null;\n\xe2\x80\xaa\xe2\x80\xa6.ReturnAsync(x);\n
Run Code Online (Sandbox Code Playgroud)\n

这样,您就可以将null与特定类型(在本例中为字符串)链接起来,因此编译器将再次知道要使用哪个重载。

\n