如何使用正确的参数测试方法的调用?

时间:2011-04-20 20:20:07

标签: c# unit-testing moq

我有一个方法,调用模拟对象的另一个方法,其参数是根据我传递给测试函数的参数计算的。
如何验证我测试的方法调用的方法是否正确调用 我正在使用Moq。

编辑:
因为没有人得到我的意思(或者我不明白你们为我解决了这个问题的事实)我会更加具体。
我有以下方法签名:

IAsyncResult BeginWrite(byte[] buffer, int offset, int size, AsyncCallback callback, object state);

在其中应该实例化一个SocketAsyncEventArgs对象并使用正确的SocketAsyncEventArgs调用它的SetBuffer方法。
SocketAsyncEventArgs是实现细节,但它是实现我之后的功能的唯一方法,因此我必须检查它是否正确调用了SetBuffer方法。 如何确保BeginWrite()实现确实使用正确的参数调用SetBuffer?

编辑2:
这里有一些代码来澄清我的意思:

public IAsyncResult BeginWrite(byte[] buffer, int offset, int size, AsyncCallback callback, object state)
{
    // No mocking can be done here
    SocketAsyncEventArgs args = new SocketAsyncEventArgs
                                    {
                                        // Proper initialization. Should be verified as well.
                                    };
    args.SetBuffer(buffer, offset, size);
    Client.SendAsync(args);
}

3 个答案:

答案 0 :(得分:6)

您可以测试是否通过Verify方法调用该方法。如果被调用的方法没有返回任何内容,那么你不需要Setup。我更喜欢这个,而不是Setup或Expect / VerifyAll方法,因为它更像是AAA。

[Test]
public void ShoudlCallMockMethod()
{
    var mocked = new Mock<IDoStuff>();

    var target = new ClassToTest(mocked.Object);
    target.DoStuff();

    mocked.Verify(x => x.CallMyMethod(It.IsAny<string>());
}

这里它希望用任何参数调用CallMyMethod。如果您知道传入的确切参数并想要检查,那么执行

mocked.Verify(x => x.CallMyMethod("exactstring"));

如果你想要传递更复杂的匹配(对于有很多araguments的复杂对象很有用),那就得look at another answer I did with using a matcher

如果你想确保只调用一次,你也可以添加Times.AtMostOnce()

[编辑]

根据您的编辑和注释,您不需要模拟args对象,但如果您仍想验证参数是否已设置,则可以在Client.SendAsync方法上进行验证,前提是可以模拟(我会建议你应该瞄准,如果你还没有这样做)。我提供的关于匹配者的链接应该有帮助。

至于你在过去几年的评论中提出的问题,记录/重播 - 验证&gt; Expect / Setup-Verify&gt; [配置] -Verify。它可以归结为模拟技术,但主要是由于在c#3.5中引入了lambda表达式,然后转向了AAA。您真正想要的是遵循AAA原则的小型可读测试,因此Expect / Setup-VerifyAll确实在编配阶段具有Assert(您必须回头查看正在验证的内容)。因此,除非模拟方法需要返回某些内容,否则您不需要安装程序,只需验证该方法是在Assert阶段调用的。

答案 1 :(得分:1)

我相信它会验证你在调用Setup时传入的参数是否等于真实代码传入的参数。

QuickStart guide有更有趣的约束的例子。遗憾的是,目前无法链接到外部API指南:(

编辑:我怀疑你想要的东西:

mock.Setup(foo => foo.SendAsync(It.Is<AsyncCallback>(x => 
           {
               // Whatever you need to test here
               return x.Buffer.Length == 15 && 
                   x.Offset = 10 &&
                   x.Count = 5;
           }));

答案 2 :(得分:0)

下面的测试失败,因为设置期望名为value的参数被传递为“预期”未被满足。我想这就是你追求的目标?

[TestClass]
public class MyTests
{
    [TestMethod]
    public void TestParameterExpectation()
    {
        var mock = new Mock<IInterface>();
        mock.Setup(x => x.CallMe("expected"));

        CallIt("not expected", mock.Object);

        mock.VerifyAll();

    }

    public void CallIt(string value, IInterface callit)
    {
        callit.CallMe(value);
    }

}

public interface IInterface
{
    void CallMe(string value);
}