应该在单元测试中模拟简单的类还是应该直接使用/测试它们?

时间:2019-11-23 15:13:37

标签: c# unit-testing mocking moq xunit.net

我不确定我的方法TranslateResponse()还能测试什么。

它基本上检查翻译器的类型并调用翻译器的关联set()方法。

public async Task TranslateResponse(Policy response)
{
    foreach (var t in await _translatorFactory.BuildTranslators())
    {
        var policyTranslator = t as IPolicyAwareTranslator;
        policyTranslator?.SetPolicy(response);
        var additionalInterestTranslator = t as IAdditionalInterestAwareTranslator;    
        additionalInterestTranslator?.SetAdditionalInterests(response.AdditionalInterests);
        var locationsTranslator = t as ILocationsAwareTranslator;
        locationsTranslator?.SetLocations(response.Locations);
    }
}

我正在为TranslateResponse()方法编写测试用例。据我了解,我正在根据提供的翻译器类型验证对相应方法的调用。 测试用例行

Mock<ITranslator> mockedTranslator = new Mock<ITranslator>(); 
mockedTranslator.Setup(t => t.Translate(_translatorDataAccessor.Object));

var mockedPolicyTranslator = mockedTranslator.As<IPolicyAwareTranslator>();
mockedPolicyTranslator.Setup(t => t.SetPolicy(It.IsAny<Policy>()));

mockedPolicyTranslator.Verify(t => t.SetPolicy(It.IsAny<Policy>()), Times.AtLeastOnce);

我的担忧是

  1. 我很好奇我是否可以测试验证电话以外的其他功能?

  2. 我应该在这里还是在自己的类中测试set()方法的逻辑?即使如此,我也无法弄清楚在Set()的测试用例中要声明什么,这将使用传入的参数设置私有字段。

public class PolicyTranslator : ITranslator, IPolicyAwareTranslator
{      
    private Policy _policy;        
    public void SetPolicy(Policy policy)
    {
        _policy = policy;
    }  
    //translate()
}      

1 个答案:

答案 0 :(得分:0)

除了验证通话,我还能测试更多东西吗?

基本上,您没有什么可以测试的,只是

  1. 为每个使用的界面添加相同的测试

也许,您可能想要

  1. 测试实现所有接口的东西实际上是作为每个接口处理的
  2. 也许还有一个测试可以验证存在一个foreach循环(多个翻译器),而不仅仅是.FirstOrDefault()
  3. 此外,BuildTranslators没有返回任何元素的情况也是有效的情况。

我应该在这里还是在自己的类中测试set()方法的逻辑?

在大多数情况下,不应在单元测试中测试SUT依赖性,因为

  1. 它可能stop是一个单元测试(如果依赖关系足够复杂)-并不是那么重要(除非您对单元测试的定义非常严格),但是如下所示。< / li>
  2. 通过其使用者测试依赖项通常会使测试不必要地复杂化
    • 您必须自行设置(通常是不重要的)依赖项。
    • 您必须自行设置其使用者/用户/ SUT。
    • 然后,您必须以实际调用该方法的方式构建测试 依赖性。
    • 然后验证依赖关系及其使用者是否按预期工作。
    • 而且测试的复杂度/数量不是线性增长的-如果您可以100%/合理地覆盖4个SUT测试及其4个依赖关系,而要达到相同程度的集成水平测试,则可能需要介于4和4 * 4甚至更多测试。

在简单的情况下,例如所讨论的代码,它实际上将简化事情,因为您不再需要模拟IPolicyAwareTranslator,并且可以简单地测试值是否按预期设置,即使在这种情况下,如果有一个小陷阱:

  1. 我们无法再确定该方法是否可以处理IPolicyAwareTranslator-有人可以将var policyTranslator = t as IPolicyAwareTranslator;替换为var policyTranslator = t as PolicyTranslator;,并且测试仍然可以通过,尽管它不再可以处理我们的关键业务AwesomePolicyAwareTranslator

您可能会说它基本上是movie-plot-threat,如果您知道自己在做什么并且不太麻烦,就可以将多个类作为一个子系统进行测试。

尽管在大多数情况下,当您可以进行适当的隔离,更简单时,我会反对这种“低级集成测试”!单元测试

低级集成测试-基本上是一个虚构的术语,但我想说它非常适合此类测试。


不过,在某些情况下,使用粗粒度的“低级集成测试”可能比使用覆盖相同代码的单元测试要好一些。

  1. 通常会在单个组件最终变得如此小时发生,以至于对它们进行单元测试不允许您表达领域概念/在众多真实场景​​中都具有真正的信任度,而测试则在{{3 }}太少/难以运行/维护。

在这种情况下,“低级集成测试”以合理的价格为您提供了很多东西(我们不要忘记100%的覆盖率是无法获得的,不能以便宜的价格建造适当的测试金字塔,因此具有成本效益)测试是必要的。