如何使用Moq存根接口方法

有没有办法使用Moq存根方法? 我看到了很多类似头衔的问题,但实际上没有一个回答我的问题。 这是我给出的unit testing示例,我发现使用Moq进行测试非常困难。 我想做的是unit testingEmailTask​​s.UserIsValidForNotice()方法:

public class User { public DateTime JoinDate { get; set; } public bool Active { get; set; } } public class EmailTasks { IUserRepository repo; public EmailTasks(IUserRepository repo) { this.repo = repo; } public IList UserIsValidForNotice(DateTime minDate) { return repo.FindAll(u => u.Active && u.JoinDate > minDate); } } public interface IUserRepository { IList FindAll(Func q); } 

我可以设置如下的存根,然后轻松测试查询,但我无法使用Moq,因为我无法访问Mocks Return函数中的方法参数。

 public class StubRepo : IUserRepository { public IList PersonList { get; set; } public IList FindAll(Func q) { return PersonList.Where(q).ToList(); } } 

我知道这可能不是最好的设计,但我只是感兴趣,如果可以使用Moq完成。

这里的问题是你在测试什么?

IMO,您应该测试的是您是否使用正确的Func调用了存储库。 你可以这样做:

 [Test] public void UserIsValidForNotice_has_correct_expression() { var repoMock = new Mock(); var sut = new EmailTasks(repoMock.Object); sut.UserIsValidForNotice(DateTime.Now); repoMock.Verify(r => r.FindAll(It.Is>(func => func(someUser)); } 

调用Verify方法时,将检查是否已调用存储库。 此外,您检查是否已使用Func的实例调用它(即It.Is<>部分。

对于It.Is<>您可以指定回调将获取传递的参数,并在参数有效时返回true,否则返回false。 因此,在该回调中,您可以对已知用户执行Func并检查它是否正确评估。

如果你仍然希望将它存根并返回一些东西,你可以这样做:

 repoMock.Setup(r => r.FindAll(It.IsAny>) .Returns, IList>(fnc => new List()); 

如果调用Returns的generics重载,则最多可以指定8个类型参数。 第一个将传递给您提供的表达式(来自实际调用),而最后一个确定返回类型。

 var personList = new List(); // set up your personList here var repoMock = new Mock(); repoMock.Setup(repo => repo.Findall(It.IsAny>()) .Return((Func q) => personList.Where(q).ToList());