有效的单元测试覆盖率(以及实际应该测试的内容?)

时间:2011-04-12 20:17:04

标签: .net web-services unit-testing tdd code-coverage

我看到有几个问题基于这个主题,但我有一些具体的例子,我正在努力。我希望有人可以在这里帮助我,因为我是新手测试驱动开发和单元测试。

(我不确定这是否重要,但我使用的是C#与.NET framework 4.0并使用Microsoft的内置测试框架)

首先,是否值得测试非常简单的代码块?例如,对于我的一个类,我有一个Fill方法,它接受10个参数,并根据这些参数设置类中10个属性的值。填充代码实际上只是一系列值设置语句。我已经读过一个好的单元测试应该只断言一件事,但在我看来,为了检查所有这些值是否已正确设置,我必须断言10件事。所以要么我根本无法测试它,相信代码足够简单,或者编写10个不同的单元测试来检查每个属性。这些都是正确的吗?

第二个例子。我有一个代码块,可以调用一个类的私有方法,最后调用一个Web服务来向用户发送一封电子邮件。我知道我应该为电子邮件服务注入一个模拟Web服务,这样我就不会测试多个类,但是我应该如何测试所有这些私有方法和那个电子邮件调用?

第三个例子与上一个例子类似。我的班级结构看起来像:

控制器---取决于---> IWidget(一些业务对象)&& IDataProvider DataProvider(实现IDataProvider)---取决于--->网络服务 WebService ---直接拨打电话--->数据库

现在我有控制器的单元测试(注入模拟Widgets和DataProviders)。 这一切都很好。我也对Widget进行了单元测试,没有任何问题。

问题归结于DataProvider和WebService。此特定实例中的WebService除了传递数据提供者的请求并传回数据(由于物理体系结构限制)之外什么都不做。

我无法对DataProvider进行单元测试,因为我不确定如何注入模拟Web服务。我也不确定单元测试DataProvider是否值得,因为我最终只需要编写很多模拟数据集来测试值。同样,我不确定如何对Web服务进行单元测试,因为在这种情况下,WebService的主要功能取决于数据库。再一次,这值得测试吗?如果WebService做了更多,除了仅作为传递但仍然依赖于数据库,该怎么办?

我非常感谢任何人可以提供这方面的建议。非常感谢。

2 个答案:

答案 0 :(得分:3)

  

我已经读过一个好的单元测试应该只断言一件事,但在我看来,为了检查所有这些值是否已正确设置,我必须断言10件事。所以要么我根本无法测试它,相信代码很简单,要么写10个不同的单元测试来检查每个属性。

我想说一个好的单元测试应该测试一个 故事用例 场景,这确实可以涉及多个断言。

如果该方法涉及10个任务,确实有可能搞砸一些,名称拼写错误等等,因此单元测试为其(小)价格提供了价值。

  

我有一个代码块,可以调用一个类的私有方法,最后调用一个Web服务来向用户发送一封电子邮件。我知道我应该为电子邮件服务注入一个模拟Web服务,这样我就不会测试多个类,但是我应该如何测试所有这些私有方法和那个电子邮件调用?

这称为传感,即感知您所做的通话的结果/副作用。答案取决于那些私有方法实际上做了什么。如果他们汇总了一些最终进入邮件消息的数据,则可以通过消息内容对其进行测试。如果他们以可从外部检测到的方式更改对象的内部状态,则可以对其进行验证。如果这些都不成立,甚至可能会将这些私有方法更好地移动到一个单独的类公共接口中,在那里它们可以进行适当的单元测试。

  

我无法对DataProvider进行单元测试,因为我不确定如何注入模拟Web服务。我也不确定单元测试DataProvider是否值得,因为我最终只需要编写很多模拟数据集来测试值。

我不一定要对这些类进行单元测试,这些类实际上是外部组件的包装器。如果那里只有绝对最小的逻辑量,即所有(或最可能的)值得测试的代码被移出到其他单元可测试的类,IMO可以将这些类的测试留给集成/功能测试,它运行连接到真实数据库,Web服务等的整个(子)系统。

答案 1 :(得分:2)

Ad Ad)
如果你只是在设置语句,你可能会争辩说你并没有真正提供任何功能。但如果你有一个老板进入代码覆盖的事情,不测试这样的方法会让你陷入困境。是的,你应该只断言一件事,但是每个属性上的IMHO断言都是通过一个方法正确设置的,那么它只算作一个断言 - 无论你的测试方法中有多少个断言语句。有时我甚至将所有断言提取到一个私有方法来说明这个

Ad Second) 如果您需要测试私有方法,那么表明您可能最好不要提取这些方法。

Ad Third)
我通过在网关类中包装所有webservice调用来避免此问题。可以模拟和注入此网关的接口。如果可能,我尝试使用所有外部通信执行此操作。

<强>更新
哎呀......弄乱了编号。现在修复它