我应该在单元测试时总是使用Mocks,以便最小化测试范围内的单元

时间:2013-03-11 11:47:40

标签: c# unit-testing mocking moq xunit

考虑以下测试,确认当一个对象被添加到HttpContentConatiner类时,它产生的MD5(存储在内容容器中)与外部序列化和散列体内容的结果相匹配(这就是它的方法)会被使用)。

[Fact]
public void When_body_added_correctly_MD5_matches_an_external_hash_of_the_same_content()
{
    var contentStub = new object();
    var serializer = new NewtonSoftJsonSerializer();
    var hasher = new Hmac256Hasher();
    var contentContainer = new HttpContentContainer(serializer, hasher);

    contentContainer.AddBody(contentStub);

    Assert.Equal(hasher.Hash(serializer.Serialize(contentStub), "Key"),
                             contentContainer.ContentMD5.Value);

}

在这个测试中,我使用了序列化器和哈希的实际实现,而不是模拟这两个对象。这现在意味着测试取决于hasher和序列化器正常工作,因为它们的实现现已被拉入测试范围,我担心这可能会使我的测试变得脆弱。

我的问题
鉴于上面的示例,我是否应该为了可维护性目的而模拟序列化程序和哈希,还是可以依赖这样的外部服务?

基于答案的新代码:

[Fact]
public void When_a_valid_body_is_added_ContentMD5_Value_is_populated()
{
    var serializerMock = new Mock<ISerializer>();
    serializerMock.Setup(serializer => serializer.Serialize(It.IsAny<object>()))
                  .Returns("serializedContent");

    var hasherMock = new Mock<IHasher>();
    hasherMock.Setup(hasher => hasher.Hash(It.IsAny<string>(), It.IsAny<string()))
              .Returns("MD5");

    var contentContainer = 
        new HttpContentContainer(serializerMock.Object, hasherMock.Object);

    contentContainer.AddBody(new object());

    Assert.NotEmpty(contentContainer.ContentMD5.Value);
}

1 个答案:

答案 0 :(得分:1)

我更喜欢Mock Hasher和Serializer。

原因 - 可以假设这些依赖关系的HashSerialize方法都执行预期的函数,这可能是模拟的期望。然后,测试失败将确定测试对象的失败。