【问题标题】:Understanding Mock Unit Testing了解模拟单元测试
【发布时间】:2014-03-17 10:57:32
【问题描述】:

我试图理解使用模拟单元测试,我从 MOQ 开始。这个问题也可以笼统地回答。

我只是想重用How to setup a simple Unit Test with Moq?中给出的代码

[TestInitialize]
public void TestInit() {
    //Arrange.
    List<string> theList = new List<string>();
    theList.Add("test3");
    theList.Add("test1");
    theList.Add("test2");

    _mockRepository = new Mock<IRepository>();

    //The line below returns a null reference...
    _mockRepository.Setup(s => s.list()).Returns(theList);
    _service = new Service(_mockRepository.Object);
}

[TestMethod]
public void my_test()
{
    //Act.
    var myList = _service.AllItems();
    Assert.IsNotNull(myList, "myList is null.");

    //Assert.
    Assert.AreEqual(3, myList.Count());
}

这是我的问题

1 .在 testInitialize 中,我们将列表计数设置为 3(字符串),我们使用 MOQ 返回相同的值,在下面的行中,我们将得到相同的结果

var myList = _service.AllItems(); //Which we know will return 3

那么我们在这里测试的是什么?

2 。单元测试失败的可能场景是什么?是的,我们可以将错误的值设为 4 并通过测试。但在实时我看不到任何失败的可能性?

我想在理解这些概念方面有点落后。我确实了解代码,但正在尝试获得见解!希望有人可以帮助我!

【问题讨论】:

    标签: asp.net-mvc unit-testing mocking moq


    【解决方案1】:

    您的示例中的被测系统 (SUT) 是 Service 类。自然地,字段 _service 使用真正的实现而不是模拟。这里测试的方法是AllItems,不要和IRepository的list()方法混淆。后一个接口是您的 SUT 服务的依赖项,因此它被模拟并通过构造函数传递给服务类。我认为您对 AllItems 方法似乎只返回其依赖项 IRepository 的 list() 方法的调用这一事实感到困惑。因此,那里没有太多的逻辑。也许,重新考虑这个示例并为 AllItems 方法添加更多预期的逻辑。例如,您可以断言 AllItems 返回由 list() 方法提供但重新排序的相同元素。

    【讨论】:

    • 服务被模拟,列表将返回,正如我在问题1中提到的那样
    • 不,只有存储库被模拟。服务,即 SUT,使用 real 实现。要回答您的问题 1) 响应是您正在测试“AllItems 返回的列表返回的元素与 IRepository 返回的列表一样多”。对于洞察力,您应该将 UnitTests 视为 SUT 应验证的合同。我上面的回答的意思是,您的 SUT 缺乏作为单元测试的好例子的逻辑,增加了 AllItems 在给定上下文中带来的逻辑的更多复杂性。给定的上下文是 Mock. 返回的列表
    • 你能分享任何我可以从这里获取的链接吗!
    • 我想你可以看看这个question。关于这个主题,我喜欢这个book
    【解决方案2】:

    我希望我能帮助你解决这个问题。

    1.) 至于这个,你基本上测试他算。有时在一个集合中,数据会累积,所以并不一定意味着每次执行代码总是3。下次运行时,它会增加3,因此它会变成6,然后是9,依此类推。

    2.) 对于单元测试,有很多失败的方法,例如错误计算、算术溢出错误等。 Here's一篇好文章。

    【讨论】:

      【解决方案3】:
      1. 测试应该验证服务与其存储库的对话是否正确。我们通过设置模拟存储库来返回一个易于验证的预设答案来做到这一点。但是,通过现在的测试:

        • 服务可以完美地返回由 3 个组成的字符串组成的任何列表,而无需与存储库通信,并且测试仍将通过建议:在模拟上使用Verify() 来检查list() 是否真的被调用了。

        • 3 在这里基本上是一个神奇的数字。对theList 的更改可能会使该数字不同步并破坏测试。 建议:使用theList.Count 而不是3。更好:不是检查列表中的元素数量,而是验证AllItems() 是否准确返回存储库传递给它的内容。您可以为此使用CollectionAssert

        这意味着将theList_mockRepositoryTestInit() 中取出,以便在更广泛的范围内或直接在TestMethod 内访问它们,这可能会更好(在这里使用TestInitialize 并没有多大用处) .

      2. 如果服务以某种方式停止与其存储库通信,如果它停止返回存储库提供给它的确切内容,或者如果存储库的合同发生更改,则测试将失败。更重要的是,如果 IRepository 的实际实现中存在错误,它不会失败 - 测试小单元可以让您将手指指向失败的确切对象而不是其邻居。 p>

      【讨论】:

        猜你喜欢
        • 2015-02-27
        • 2011-09-24
        • 1970-01-01
        • 2013-02-22
        • 2011-04-11
        • 2020-05-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多