Lad*_*nka 6 .net c# tdd unit-testing mocking
编辑:
似乎通过尝试为我自己的问题提供一些解决方案,我模糊了整个问题.所以我正在修改这个问题.
假设我有这个课程:
public class ProtocolMessage : IMessage
{
public IHeader GetProtocolHeader(string name)
{
// Do some logic here including returning null
// and throw exception in some cases
return header;
}
public string GetProtocolHeaderValue(string name)
{
IHeader header = GetProtocolHeader(name);
// Do some logic here including returning null
// and throw exception in some cases
return value;
}
}
Run Code Online (Sandbox Code Playgroud)
实际上,在这些方法中发生的事情并不重要.重要的是我有多个单元测试来覆盖GetProtocolHeader涵盖所有情况的方法(返回正确的标题,null或异常),现在我正在编写单元测试GetProtocolHeaderValue.
如果GetProtocolHeaderValue依赖于外部依赖,我将能够模拟并注入它(我正在使用Moq + NUnit).然后我的单元测试将测试期望外部依赖被调用并返回预期值.外部依赖将通过自己的单元测试进行测试,我会完成但是如何在这个示例中正确进行,其中方法不是外部依赖?
澄清问题:
我相信我的测试套件GetProtocolHeaderValue必须测试GetProtocolHeader返回header,null或exception的情况.所以主要的问题是:我应该编写GetProtocolHeader真正执行的测试(一些测试将被复制,因为它们将测试相同的代码作为GetProtocolHeader自己的测试)或者我应该使用@adrift和@Eric Nicholson描述的模拟方法,我不会运行实时GetProtoclHeader但只是配置mock以在调用此方法时返回header,null或exception?
在调用时GetProtocolHeaderValue,您实际上需要知道它是否调用过吗GetProtocolHeader?
当然,只要知道它从正确的标头中获取了正确的值就足够了。它实际上是如何得到的与单元测试无关。
您正在测试功能单元,功能单元GetProtocolHeaderValue是在给定标头名称的情况下是否返回预期值。
确实,您可能希望防止不适当的缓存或交叉污染或从不同的标头获取值,但我不认为测试它所调用的GetProtocolHeader是做到这一点的最佳方法。您可以推断它以某种方式获取了正确的标头,因为它返回了标头的预期值。
只要您以确保重复标头不会掩盖错误的方式设计测试和测试数据,那么一切都应该很好。
如果GetProtocolHeader工作快速、可靠并且是幂等的,那么我仍然认为没有必要嘲笑它。这三个方面中任何一个方面的不足都是(IMO)嘲笑的主要原因。
如果(正如我从问题标题中怀疑的那样),您希望模拟它的原因是设置适当状态以返回实际值所需的前导码太冗长,并且您不想在两个测试中重复它,为什么不在设置阶段做呢?
良好的单元测试所扮演的角色之一就是文档。
如果有人希望知道如何使用您的类,他们可以检查测试,并可能复制和更改测试代码以适应他们的目的。如果真正的使用习惯被模拟的创建和注入所掩盖,这就变得很困难。
模拟可以掩盖潜在的错误。
假设GetProtocolHeader如果 name 为空,则会抛出异常。您相应地创建一个模拟,并确保GetProtocolHeaderValue适当地处理该异常。后来,您决定GetProtocolHeader应该返回null一个空名称。如果您忘记更新模拟,GetProtocolHeaderValue("")那么现在在现实生活中与测试套件中的行为会有所不同。
如果模拟比设置更简洁,则模拟可能会带来优势,但首先要适当考虑上述几点。
尽管您给出了需要测试的三个不同GetProtocolHeader响应(标头、空或异常)GetProtocolHeaderValue,但我想第一个可能是“一系列标头”。(例如,它如何处理存在但为空的标头?它如何处理前导和尾随空格?非 ASCII 字符呢?数字?)。如果所有这些的设置都非常冗长,那么模拟可能会更好。