使用MOQ设置和返回的正确方法

时间:2014-07-28 10:01:56

标签: c# unit-testing mocking moq

我是MOQ的新手,我对安装方法有点困惑。下面的示例显示了我需要测试的一种方法。测试中的方法返回两个日期的最新时间,因此我创建了两个日期时间对象并将它们传递给我的函数。我感到困惑的部分是回复电话。这会忽略我方法中的逻辑并返回我告诉它的内容。例如,如果我说返回(date2),则无论逻辑如何,断言都会通过。我做错了吗?

        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 个答案:

答案 0 :(得分:0)

你以错误的方式使用Moq。它旨在替换您测试的类所依赖的某些实现。例如,您正在测试一些使用DB存储库的类:

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个不同测试失败的情况。