正确使用MOQ的setup和returns方法

9

我是MOQ的新手,对于setup方法有点困惑。下面的例子展示了一个我需要测试的方法。被测试的方法返回两个日期中的最新时间,所以我创建了两个datetime对象并将它们传递给我的函数。我困惑的部分是returns调用。这忽略了我的方法中的逻辑并返回我告诉它的内容。例如,如果我说returns(date2),那么无论逻辑如何,assert都会通过。我做错了什么吗?

public virtual DateTime LatestTime(DateTime t1, DateTime t2)
{
   if (t1.CompareTo(t2) > 0)
      return t1;

    return t2;
}

[Test]
[Category("Catalogue service")]
public void TestLatestTimeReturnsCorrectResult()
{
    //Arrange
    DateTime date1 = new DateTime(2014, 07, 25, 13, 30, 01);
    DateTime date2 = new DateTime(2014, 07, 25, 13, 30, 00);

    MockCatalogueService.Setup(x => x.LatestTime(date1, date2)).Returns(date2);

    //Act
    DateTime retDate = MockCatalogueService.Object.LatestTime(date1, date2);

    //Assert
    Assert.That(retDate == date2);
}
1个回答

20

您在错误的方式下使用了Moq。它的作用是替换您测试类所依赖的一些实现。例如,您正在测试某个使用数据库存储库的类:

public class MyService
{
    private IMyDbRepository _repos;
    
    public MyService(IMyDbRepository dbRepos)
    {
        _repos = dbRepos;
    }

    public string[] GetClientNames()
    {
        return _repos.GetAllClients().Where(c=>!c.IsDisabled).OrderBy(c=>c.Name).ToArray();
    }
}
你需要测试 GetClientNames() 方法,但在拥有 IMyDbRepository 实例之前是不可能的。创建和填充数据库只为了测试客户端排序和筛选方法太过复杂且错误。解决方法是使用 Moq
[Test]
public void TestGetAllClientsDoesNotReturnDisabledUsers()
{
    var dbReposMock = new Mock<IMyDbRepository>();
    dbReposMock.Setup(r=>r.GetAllClients()).Returns(
                      new []{ new Client { Name="AAA", IsDisabled=true },
                              new Client { Name="BBB", IsDisabled=false } });

    var myTestingService = new MyService(dbReposMock.Object);//You pass here the autogenerated object which follows the described primitive behavior without requiring DB at all.
    var clientNames = myTestingService.GetClientNames();
    Assert.AreEqual(1, clientNames.Length);
    Assert.AreEqual("BBB", clientNames[0]);
}

因此,Moq 允许您在运行时动态生成伪造的类(非密封)或接口实现,并将其用于使测试功能与其他功能分离。因此,如果数据库结构中出现错误,则只有少数数据库测试失败,并且可以轻松确定问题,相比于如果您没有使用 Moq 将代码解耦合,可能会导致来自所有层的 100 个不同的测试失败。


1
是的,我正在这样使用MOQ。因为该方法在我的服务API中,所以我试图错误地使用MOQ。实际上,我甚至不需要MOQ进行测试,只需要NUnit即可。感谢您的帮助。 - Jed I

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接