如何使用参数化基类为子类编写单元测试

时间:2017-06-19 21:26:14

标签: c# unit-testing nunit-3.0

鉴于我在一个名为GBase的程序集中有一个类,其中一个构造函数接受2个参数和GBase的子类(称之为GDerived),它采用相同的参数,我如何将它们分开以便我可以对子类进行单元测试?

在OtherAssembly中:

public class GBase
{
  public GBase(ParamType1 param1, ParamType2 param2)
  {
    ...
  }

  protected ParamType1 SomeProperty { get; set; }

// other stuff
}

在ThisAssembly中:

public class GDerived : GBase
{
  public GDerived(ParamType1 param1, ParamType2 param2)
      :base(param1, param2)
  {
    // new code 

    SomeProperty = newCalculatedValue;

    // other stuff
  }

// other stuff
}

原始GBase类是遗留代码,程序的一般结构也是如此 - 由于代码库大小(10k行加),改变结构是不可能的 - 没有一个曾经编写过单元测试直到最近。

所以现在我想为子类构造函数编写一个测试(使用NUnit)来验证是否使用正确的值填充了正确的属性。请注意,测试类与测试类位于同一项目中。

[TestFixture]
public class GDerivedTests
{
  [Test]
  public void GDerivedConstructor_ValidParams_PropertiesSetCorrectly()
  {
    var newGDerived = new GDerived(parameter1, parameter2);

    Assert.That(SomeProperty == parameter1;
  }
}

这是我们必须处理的非常粗略的代表,除了在我们需要测试的基类中设置属性之外,还有其他情况。我甚至不知道从哪里开始。我有Michael Feathers的书“有效地使用Legacy Code”,但它似乎并没有涵盖这种普遍的“设计模式”,在我们正在处理的代码中广泛使用。是因为它如此简单,任何闪烁的idjyot应该知道如何处理它,还是因为它是一个罕见的情况?我不知道是不是,但我可能错了......

我想到的一种可能的方法是为基类提取接口并模拟基类构造函数 - 但我不确定如何执行此操作的详细信息。请注意,我们都是团队测试的相关新手,没有经验可以借鉴。不编码新手,只是单元测试新手。

TIA, 戴夫

1 个答案:

答案 0 :(得分:1)

首先:保持简单!在您的示例中,您唯一可以测试的是var colorizer = {} colorizer['white'] = { 'colors_body': 'FFFFFF', 'colors_wrapper': 'E6E6E6', 'colors_footer': 'CCCCCC' } colorizer['dark'] = { 'colors_body': 'EBEEF2', 'colors_wrapper': 'B2B5B8', 'colors_footer': '1A2758' } $('input[name="colorizer"]').change(function() { var color = $(this).val(); $.each(colorizer[color], function(i,v) { $('#'+i+' input').val(v); }); }); 。其他所有内容都在基类中,您似乎不想测试,因此测试方法SomeProperty毫无意义。从长远来看,对它进行测试可能是明智的。

测试通常包含三个称为AAA的元素:Arrange,Act和Assert。所以写下你的测试:

GDerivedConstructor_ValidParams_PropertiesSetCorrectly()

这是一个开始。从这里开始您很快就会看到您获得了大量冗余代码,因此您可能需要在一段时间后对其进行重新设计。

Mocking对于测试基类或基类对注入的对象做一些奇怪的事情是有意义的。在这种情况下,传入模拟而不是真实对象。我个人会使用一个为您完成所有工作的模拟框架,您也可以使用它来测试基类本身。一个着名的例子是moq

旁注:如果将测试类移动到自己的项目中,你会更好。不应出于各种原因发布测试代码,如果它们分开,构建,测试和部署可能会变得更容易。