Moq - 将参数从 setup() 传递到 returns()

sta*_*eUp 8 c# moq xunit

我不确定如何在 Moq 中将参数从 Setup() 传递到 Returns() 。

这是一个例子:

public static IInterfaceHandler GetInterfaceHandlerMoq()
{
   // Defining the moq
   var moq = new Mock<IInterfaceHandler>();

   // Trying to set up a moq using another moq
   moq.Setup(m => m.CreateCommunicationInterface(It.IsAny<Guid>(), It.IsAny<string>()))
       .Returns((Guid guid, string value) => GetProgrammerMoq(guid, value));

   // Return mocked object
   return moq.Object;
}
Run Code Online (Sandbox Code Playgroud)

请注意,GetProgrammerMoq() 是一个将返回另一个 Moq 的库。这是代码:

public static IProgrammer GetProgrammerMoq(Guid guid, string instName)
{
    // Create Moq
    var moq = new Mock<IProgrammer>();

    // Set up the returnables
    moq.Setup(o => o.InstanceName).Returns(programmer + "_" + instName);
    moq.Setup(o => o.Guid).Returns(guid);

    // Return mocked object
    return moq.Object;
}
Run Code Online (Sandbox Code Playgroud)

请参阅此处,GetProgrammerMoq() 需要根据传递给 CreateCommunicationInterface() 的内容来设置其参数。

然后,我的测试尝试获取并使用 Moq,但“p”返回为 null(因为我猜,我的参数没有正确传递给 Returns())。
以下是测试的草稿:

[Fact]
public void DoSomething()
{
    IInterfaceHandler test = ProgrammerMoqs.GetInterfaceHandlerMoq();

    Guid? g = new Guid();
    IProgrammer p = test.CreateCommunicationInterface(g, "test-boff");

    ...
}
Run Code Online (Sandbox Code Playgroud)

que*_*atl 10

尝试这个:

\n
   var moq = new Mock<IInterfaceHandler>(MockBehavior.Strict);\n
Run Code Online (Sandbox Code Playgroud)\n

MockBehavior.Strict:如果你从 Mock 中得到 NULL,那么总是尝试 MockBehavior.Strict。当某些设置未准备好时,Moq 默认返回 NULL。但使用 MockBehavior.Strict 时,它会抛出异常。如果缺乏正确的设置,每次尝试从模拟对象调用任何内容都会抛出异常。

\n

如果您在尝试 MockBehavior.Strict 时遇到异常,则意味着:

\n
.Setup(m => m.CreateCommunicationInterface(It.IsAny<Guid>(), It.IsAny<string>()))\n
Run Code Online (Sandbox Code Playgroud)\n

未能捕获调用,因此模拟默认返回 NULL。

\n

为什么它无法捕获调用?有几种选择:

\n
    \n
  • CreateCommunicationInterface 可能已重载,并且您的设置与您未预料到的另一个重载相匹配
  • \n
  • 过滤器 (It.IsAny..) 与实际参数不匹配
  • \n
  • (..)
  • \n
\n

Klaus G\xc3\xbctter 在评论中指出了Guid和的区别Guid?。事实上,在您通过的测试中,您使用的过滤器是 It.IsAny():

\n
Guid? g = new Guid();\n
Run Code Online (Sandbox Code Playgroud)\n

g不是 类型的对象Guid,而是Nullable<Guid>,因此寻找 any- 的过滤器Guid不匹配。代码已编译,因为表达式的结果It.IsAny<Guid>()符合Guid?方法所需,但类型仍然不匹配。

\n

如果您尝试 It.IsAny<Guid?>() 它可能会很好地匹配并返回您想要的内容。

\n
moq.Setup(m => m.CreateCommunicationInterface(It.IsAny<Guid?>(), It.IsAny<string>()))\n   .Returns((Guid? guid, string value) => GetProgrammerMoq(guid, value));\n
Run Code Online (Sandbox Code Playgroud)\n