在实际实施和模拟中混合使用是否有测试气味?

时间:2011-03-23 18:19:45

标签: c# unit-testing design-patterns dependency-injection

我有一个消费者类负责消费字符串并决定如何处理它。它可以解析并将解析数据插入数据库中或通知管理员。

以下是我的实施。

public void Consume(string email)
{
    if(_emailValidator.IsLocate(email))
    {
        var parsedLocate = _parser.Parse(email);

        // Insert locate in database
    }
    else if(_emailValidator.IsGoodNightCall(email))
    {
        // Notify email notifying them that a locate email requires attention.
        _notifier.Notify();
    }
}

以下是我的单元测试。

// Arrange
var validator = new EmailValidator();
var parser = new Mock<IParser>();
var notifier = new Mock<INotifier>();
var consumer = new LocateConsumer(validator, parser.Object, notifier.Object);
var email = EmailLiterals.Locate;

// Act
consumer.Consume(email);

// Assert
parser.Verify(x => x.Parse(email), Times.Once());

在单元测试中混合模拟和真实实现是代码味道吗?另外,如何总是必须测试方法abc()是否总是运行一次?每当我在if块中添加一个函数时添加一个新的单元测试,这似乎是不正确的。似乎如果我继续添加到我的Consume方法,我就会创建一个陷阱。

谢谢。

3 个答案:

答案 0 :(得分:8)

要进行挑剔,单元测试是一种自动测试,可以单独测试一个单元。如果你组合两个或更多单位,它不再是单元测试,它是集成测试

但是,根据您集成的单元类型,进行大量此类集成测试可能还不错。

Krzysztof Kozmic最近写了一篇关于这篇文章的博客文章,他描述了Castle Windsor has very few unit tests,但是有很多集成测试。 AutoFixture在这些类型的集成测试中也占很大比例。我认为最重要的一点是,作为一般规则,集成不得跨越库边界

在任何情况下,您都可以将实际实现视为Test Double Continuum的一个极端,正如有些情况下使用Stubs,Mocks,Spies或者假货,还有场景,其中实际的实施可能有意义

但是,请记住,您不再需要单独测试单元 ,因此您确实在单元之间引入了使每个单独更改变得更加困难

总而言之,我仍然认为它是气味,因为它应该永远是一个停下来思考的机会。然而,气味表明只有这一点,有时,一旦你考虑过它,你就可以决定继续前进。

答案 1 :(得分:3)

我会说强烈的是。单元测试应该没有组件之间的依赖关系。

答案 2 :(得分:3)

> Is it a test smell to mix in real implementation and mocks?

这是集成测试(组合2个或更多模块)而不是单元测试(单独测试一个模块)

我的回答是:我认为在集成测试中进行模拟是可以的。