繁体   English   中英

与Moq嘲笑代表

[英]Mocking delegates with Moq

我有一个界面:

public interface IRepeater
{
    void Each(string path, Action<string> action);
}

我想用Moq模拟这个界面。 现在我显然可以做到以下几点:

var mock = new Mock<IRepeater>();
mock.Setup(m => m.Each(It.IsAny<string>(), It.IsAny<Action<string>>());

但是,以帮助测试中,我希望能够嘲笑string获取传递到Action<string> 这可以用Moq完成吗? 如果有,怎么样?

更新

为了澄清我正在测试一个依赖于IRepeater的不同class 我想模拟IRepeater.Each所以我可以控制Action获取的string ,以便我可以测试行为。

所以,如果我有这样的class

 public class Service { private readonly IRepeater _repeater; public Service(IRepeater repeater) { _repeater = repeater; } public string Parse(string path) { var builder = new StringBuilder(); _repeater.Each(path, line => builder.Append(line)); return builder.ToString(); } } 

我如何模拟IRepeater.Each以便我可以测试Service.Parse

你必须使用callback方法。 由于line => builder.Append(line)是方法行为的一部分,因此在测试方法时必须执行此行为:

    [TestMethod]
    public void Test_Service_When_Passing_String_And_ActionDelegate()
    {
        var fakeReporter = new Mock<IRepeater>();

        fakeReporter.Setup(x => x.Each(It.IsAny<string>(), It.IsAny<Action<string>>()))
            .Callback<string, Action<string>>((s, action) => action(s));

        var target = new Service(fakeReporter.Object);

        var result = target.Parse("asdfghj");

        Assert.AreEqual("asdfghj", result);
    }

测试此方法的另一种方法是验证使用正确的路径调用方法,然后验证操作是否是正确的操作:

     [TestMethod]
    public void Test_Service_When_Passing_String_And_ActionDelegate()
    {
        var fakeReporter = new Mock<IRepeater>();

        fakeReporter.Setup(x => x.Each(It.IsAny<string>(), It.IsAny<Action<string>>()))
            .Callback<string, Action<string>>((s, action) =>
            {
                Assert.AreEqual("asdfghj", s);
                foreach (var w in "pass")
                {
                    action(w.ToString());
                }
            });

        var target = new Service(fakeReporter.Object);

        var result = target.Parse("asdfghj");

        Assert.AreEqual("pass", result);
    }

顺便说一句,你可以用It.IsAny<string>()替换It.IsAny<string>() ,然后删除Assert.AreEqual("asdfghj", s); (我只想以明确的方式测试事物......)

好像您希望验证传递的Action(委托)是否会传递给IRepeater Call。 因为您没有测试Repeater而是Repeater调用者(Repeater是模拟器而不是测试对象)。

我将如何做到这一点:

public class Service
{
    private readonly IRepeater repeater;

    public Service(IRepeater repeater)
    {
        this.repeater = repeater;
    }

    public void Foo(string str, Action<string> action)
    {
        repeater.Each(str, action);
    }
}

public class ActionImplement
{
    public virtual void Action(string str)
    {
        Console.Write(str);
    }
}

public interface IRepeater
{
    void Each(string path, Action<string> action);
}

测试将验证ActionImplement.Action的传递

    [TestMethod]
    public void Test_Service_When_Passing_String_And_ActionDelegate()
    {
        var actionImplement = new Mock<ActionImplement>();
        actionImplement.Setup(m => m.Action(It.IsAny<string>()));

        var mock = new Mock<IRepeater>();
        mock.Setup(m => m.Each(It.IsAny<string>(), actionImplement.Object.Action));


        var srv = new Service(mock.Object);
        srv.Foo("aa",actionImplement.Object.Action);


        mock.Verify(ai => ai.Each("aa", actionImplement.Object.Action));


    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM