【问题标题】:How can I stub an interface method using Moq如何使用 Moq 存根接口方法
【发布时间】:2014-02-28 17:40:23
【问题描述】:

有没有办法使用 Moq 来存根方法?我看到不少标题相似的问题,但没有一个真正回答了我的问题。这是给我的一个单元测试示例,我发现使用 Moq 进行测试非常困难。我想做的是对 EmailTask​​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<User> UserIsValidForNotice(DateTime minDate)
    {
        return repo.FindAll(u => u.Active && u.JoinDate > minDate);
    }
}

public interface IUserRepository
{
    IList<User> FindAll(Func<User, bool> q);
}

我可以像下面这样设置一个存根,然后轻松地测试查询,但我无法使用 Moq 做到这一点,因为我无法访问 Mocks Return 函数中的方法参数。

public class StubRepo : IUserRepository
{
    public IList<User> PersonList { get; set; }

    public IList<User> FindAll(Func<User, bool> q)
    {
        return PersonList.Where(q).ToList();
    }
}

我知道这可能不是最好的设计,但我只是想知道这是否可以使用 Moq 来完成。

【问题讨论】:

    标签: c# unit-testing moq


    【解决方案1】:

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

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

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

    当您调用验证方法时,您会检查存储库是否已被调用。此外,您检查它是否已使用 Func&lt;User, bool&gt; 的实例调用 (即It.Is&lt;&gt; 部分。

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

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

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

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

    【讨论】:

    • 非常感谢,我唯一不喜欢第一种方法的是断言失败时返回的神秘消息。
    【解决方案2】:
    var personList = new List<User>(); // set up your personList here
    var repoMock = new Mock<IUserRepository>();
    repoMock.Setup(repo => repo.Findall(It.IsAny<Func<User, bool>>())
        .Return((Func<user, bool> q) => personList.Where(q).ToList());
    

    【讨论】:

      猜你喜欢
      • 2012-05-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多