鉴于我在一个名为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, 戴夫
答案 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。
旁注:如果将测试类移动到自己的项目中,你会更好。不应出于各种原因发布测试代码,如果它们分开,构建,测试和部署可能会变得更容易。