使用 Moq 测试接受委托的方法

Kra*_*zek 5 c# delegates unit-testing moq

我的代码正在使用一个实现这样的接口的组件

public interface IFoo 
{ 
    void DoSomething(string p1);

    void DoSomething(string p1, Action<string> p2);
}
Run Code Online (Sandbox Code Playgroud)

到目前为止,我正在使用第一种方法,但我计划转向第二种方法,我希望尽可能保持高覆盖率。

只是我真的不知道如何检查委托,甚至不知道如何设置 Moq 来模拟界面。

我试过

mock.Setup(p => p.DoSomething(It.IsAny<string>(), It.IsAny<Delegate>()));
mock.Setup(p => p.DoSomething(It.IsAny<string>(), It.IsAny<Action<string>>()));
Run Code Online (Sandbox Code Playgroud)

但也不会让我建造。有什么建议吗?

Jep*_*sen 5

线路:

mock.Setup(p => p.DoSomething(It.IsAny<string>(), It.IsAny<Delegate>()));
Run Code Online (Sandbox Code Playgroud)

不能编译becaueDoSomething需要Action<string>,而Delegate不是隐式转换为Action<string>。您的另一条线路:

mock.Setup(p => p.DoSomething(It.IsAny<string>(), It.IsAny<Action<string>>()));
Run Code Online (Sandbox Code Playgroud)

有效并且是正确的!

您只能在p2满足某些条件时进行设置,例如:

mock.Setup(p => p.DoSomething(It.IsAny<string>(),
    It.Is((Action<string> p2) => p2 != null && p2.Target is SomeClass)
    ));
Run Code Online (Sandbox Code Playgroud)

或者你可以CallBack用来检查事物:

mock.Setup(p => p.DoSomething(It.IsAny<string>(), It.IsAny<Action<string>>()))
    .CallBack((string p1, Action<string> p2) =>
    {
        // your code (for example Asserts) here,
        // use p2
    });
Run Code Online (Sandbox Code Playgroud)

当然,检查 an 的数量是有限制的Action<string>,但是您可以查看它是否为非空,查看其p2.Target是否为非空或具有特定类型或等于给定实例,您可以查看它是否p2.Method为已知(命名)方法,或者p2.GetInvocationList()如果您期望所谓的多播委托,则可以使用。