我有一个界面:
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>>());
但是,为了帮助测试,我希望能够模拟传递给Action< string>的字符串.这可以用Moq完成吗?如果有,怎么样?
更新
为了澄清我正在测试一个依赖于IRepeater的不同类.我想模拟IRepeater.Each所以我可以控制Action获取的字符串,以便我可以测试行为.
例
所以,如果我有这样的课程.
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?
解决方法
你必须使用回调方法.由于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>(),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>(),然后删除Assert.AreEqual(“asdfghj”,s);(我只想以明确的方式测试事物……)