我试图理解使用模拟单元测试,我开始与最小起订量。这个问题也可以一般地回答。
我只是想重用在如何设置一个简单的单元测试与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,测试不及格。但在现实中,我看不到任何失败的可能性?
我想我对这些概念的理解有点落后。我确实理解代码,但我正试图获得洞察力!!在您的示例中被测试的系统(SUT)是Service类。当然,字段_service使用的是真实的实现,而不是模拟。这里测试的方法是AllItems,不要与IRepository的list()方法混淆。后一个接口是SUT服务的依赖项,因此它被模拟并通过构造函数传递给Service类。我认为您对AllItems方法似乎只返回其依赖IRepository的list()方法的调用这一事实感到困惑。因此,这里没有太多的逻辑。也许,可以重新考虑这个示例,并为AllItems方法添加更多预期的逻辑。例如,您可以断言AllItems返回list()方法提供的相同元素,但重新排序。
希望我能帮到你。
1)。至于这个,你基本上是在测试他的计数。有时在集合中,数据会累积,因此并不一定意味着每次执行代码时总是3。下次运行时,它会加上3,这样它就变成了6,然后是9,以此类推。
2)。对于单元测试来说,失败的原因有很多,比如错误的计算、算术溢出错误等等。
-
测试应该验证服务是否正确地与其存储库进行通信。为此,我们设置mock Repository以返回易于验证的固定答案。然而,现在的测试是:
-
服务可以完美地返回任何3个组成字符串的列表,而不需要与存储库通信,并且测试仍然会通过。建议:在mock上使用
Verify()
来检查list()
是否真的被调用了 -
3基本上是一个神奇的数字。更改
theList
可能会使该数字不同步并破坏测试。建议:用theList.Count
代替3。更好的做法是:不要检查列表中元素的数量,而要验证AllItems()
是否准确地返回了Repository传递给它的内容。您可以使用CollectionAssert
。
这意味着将
theList
和_mockRepository
从TestInit()
中取出,以便在更广泛的范围内或直接在TestMethod
中访问它们,这可能更好(这里没有太多使用TestInitialize
)。 -
-
如果服务以某种方式停止与其存储库通信,如果它停止返回存储库提供给它的内容,或者存储库的合约更改,测试将失败。更重要的是,如果IRepository的实际实现中有错误,它不会失败——测试小单元可以让您指出失败的确切对象,而不是它的邻居。