gpt4 book ai didi

c# - 模拟不起作用时如何让我的单元测试保持干燥?

转载 作者:太空狗 更新时间:2023-10-29 21:10:11 25 4
gpt4 key购买 nike

编辑:

似乎通过尝试为我自己的问题提供一些解决方案,我模糊了整个问题。所以我稍微修改了这个问题。

假设我有这个类:

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;
}
}

这些方法中发生了什么实际上并不重要。重要的是我有多个单元测试来覆盖 GetProtocolHeader 方法,涵盖所有情况(返回正确的 header 、null 或异常),现在我正在为 GetProtocolHeaderValue 编写单元测试。

如果 GetProtocolHeaderValue 将依赖于外部依赖项,我将能够模拟它并注入(inject)它(我正在使用 Moq + NUnit)。然后我的单元测试将只测试调用外部依赖并返回预期值的期望。外部依赖将通过它自己的单元测试进行测试,我会完成但是如何在这个方法不是外部依赖的例子中正确地进行?

问题的澄清:

我相信我的 GetProtocolHeaderValue 测试套件必须测试 GetProtocolHeader 返回 header 、null 或异常的情况。所以主要问题是:我应该在真正执行 GetProtocolHeader 的地方编写测试(一些测试将被重复,因为它们将测试与 GetProtocolHeader 本身的测试相同的代码)还是应该我使用@adrift 和@Eric Nicholson 描述的模拟方法,我不会运行真正的GetProtoclHeader,而是配置模拟以在调用此方法时返回 header 、null 或异常?

最佳答案

在调用GetProtocolHeaderValue时,你真的需要知道它是否调用了GetProtocolHeader吗?

当然,知道它从正确的 header 中获取正确的值就足够了。它实际上是如何得到它的与单元测试无关。

您正在测试功能单元,GetProtocolHeaderValue 的功能单元是它是否在给定 header 名称的情况下返回预期值。

的确,您可能希望防止不适当的缓存或交叉污染或从不同的 header 获取值,但我认为测试它调用 GetProtocolHeader 不是最好的方法来做到这一点。您可以推断它以某种方式获取了正确的 header ,因为它返回了 header 的预期值。

只要您以确保重复 header 不会掩盖错误的方式设计测试和测试数据,那么一切都应该很好。

编辑更新的问题:

  1. 如果 GetProtocolHeader 工作快速、可靠并且是幂等的,那么我仍然认为没有必要模拟它。这三个方面中任何一个方面的不足都是 (IMO) mock 的主要原因。

    如果(正如我从问题标题中怀疑的那样),您希望 mock 它的原因是设置适当状态以返回真实值所需的序言过于冗长,您不想重复这两个测试,为什么不在设置阶段做呢?

  2. 良好的单元测试所扮演的角色之一是文档

    如果有人想知道如何使用您的类(class),他们可以检查测试,并可能复制和更改测试代码以满足他们的目的。如果使用的真正习语已被模拟的创建和注入(inject)所掩盖,这将变得困难。

  3. 模拟可以掩盖潜在的错误。

    假设 GetProtocolHeader 在名称为空时抛出异常。您相应地创建一个模拟,并确保 GetProtocolHeaderValue 适本地处理该异常。后来,您决定 GetProtocolHeader 应该为空名称返回 null。如果您忘记更新模拟,GetProtocolHeaderValue("") 现在在现实生活中的行为与测试套件不同。

  4. 如果模拟比设置更简洁,则模拟可能会带来优势,但请先适当考虑以上几点。

    尽管您给出了 GetProtocolHeaderValue 需要测试的三种不同的 GetProtocolHeader 响应(header、null 或 exception),但我想第一个很可能是“一个范围标题”。 (例如,它如何处理存在但为空的 header ?它如何处理前导和尾随空格?非 ASCII 字符呢?数字?)。如果所有这些的设置都非常冗长,那么模拟可能会更好。

关于c# - 模拟不起作用时如何让我的单元测试保持干燥?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8359696/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com