了解模拟单元测试

时间:2014-03-17 10:57:32

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

我试图理解使用模拟单元测试,我开始使用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中,我们将List计数设置为3(字符串),我们使用MOQ返回相同的值,在下面的行中我们将得到相同的

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

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

2。单元测试失败的可能情况是什么?是的,我们可以将错误的值设为4并且测试失败。但实时我没有看到任何失败的可能性?

我认为理解这些概念并不落后。我确实理解代码,但我正试图获得见解!希望有人可以帮助我!

3 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:0)

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

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

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

答案 2 :(得分:0)

  1. 该测试应该验证服务是否正确地与其存储库进行通信。我们通过设置模拟存储库来返回一个易于验证的固定答案。但是,现在进行测试:

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

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

    这意味着从theList中获取_mockRepositoryTestInit(),以便在更广泛的范围内或直接在TestMethod内访问它们,这可能会更好(无论如何)在这里使用TestInitialize

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