Unit testing 单元测试模板法设计模式
假设以下模板方法实现:Unit testing 单元测试模板法设计模式,unit-testing,language-agnostic,tdd,Unit Testing,Language Agnostic,Tdd,假设以下模板方法实现: public abstract class Abs { void DoYourThing() { log.Info("Starting"); try { DoYourThingInternal(); log.Info("All done"); } catch (MyException ex) { log.Error("Somethin
public abstract class Abs
{
void DoYourThing()
{
log.Info("Starting");
try
{
DoYourThingInternal();
log.Info("All done");
}
catch (MyException ex)
{
log.Error("Something went wrong here!");
throw;
}
}
protected abstract void DoYourThingInternal();
}
现在,关于如何测试Abs
类,并确保调用doyourthingininternal
有很多信息。但是,假设我想测试我的
Conc
类:
public class Conc : Abs
{
protected override void DoYourThingInternal()
{
// Lots of awesome stuff here!
}
}
我不想执行conc.DoYourThing()
,因为这将调用已经单独测试过的父方法
我只想测试重写方法
有什么想法吗 在Abs上粘贴一个界面并模仿它怎么样?忽略这些调用,或者对它们设置期望值?我认为部分“问题”在于无法从类外部调用受保护的方法。从
Conc
派生并提供新公共方法的mock类如何:
public class MockConc: Conc
{
void MockYourThingInternal()
{
DoYourThingInternal()
}
}
您已将问题标记为“tdd”,但我怀疑您在遇到此“问题”时是否遵循了该原则 如果你真的遵循tdd,你的工作流程会是这样的
如果您开始考虑测试哪些代码行,那么您就失去了编写测试的许多好处。你想确保你的逻辑工作-为这个而写测试。 < P>我不认为<代码> doYuthInIngalAudio()/代码>与<代码> doyththin()/代码>(如,在两个单独的代码模块中,可以单独测试)因为无论如何你都不能单独实例化你的抽象类,这两个方法总是一起运行。此外,
doyourthingininternal()
可以访问类中所有受保护的成员,并可以修改它们,这可能会对DoYourThing()
产生副作用。因此,我认为与DoYourThingInternal()
的具体实现完全隔离地测试DoYourThingInternal()
是危险的
但是,这并不意味着您不能对DoYourThing()
的预期行为进行单独的测试,这在所有Abs实现中必须保持不变,而DoYourThingInternal()
的预期行为也必须保持不变
您可以使用一个(抽象)基本测试类,在该类中,您可以为DoYourThing()
中预期的一般行为定义一个测试。然后创建与Abs实现一样多的测试子类,并对每个实现的细节进行单元测试
来自基本测试类的测试将被继承,当您运行任何子类的测试时,DoYourThing()
的继承测试也将运行:
公共抽象类AbsBaseTest
{
公共摘要Abs GetAbs();
[测试]
public void TestSharedBehavior()
{
getAbs().DoYourThing();
//在此处测试共享行为。。。
}
}
[测试夹具]
公共类测试:AbsBaseTest
{
公共覆盖Abs GetAbs()
{
返回新的AbsImpl();
}
[测试]
公共无效测试特定行为()
{
getAbs().DoYourThing();
//在这里测试特定的行为
}
}
看
但是,我不知道抽象测试类继承是否受到所有单元测试框架的支持(我认为NUnit是这样的)。您可以通过几种方法来实现,其中许多方法已经在这里进行了说明。以下是我通常采用的方法:让测试用例从具体类继承
public ConcTest : Conc
{
[Test]
public void DoesItsThingRight()
{
var Result = DoItsThingInternal();
// Assert the response
}
}
希望有帮助
布兰登我明白你的意思。这是有道理的。但是,如果我按照您的建议多次测试某些代码行,这意味着如果我更改这些代码行,我需要更改多个测试。这可能是一个很高的代价…(假设我们现在讨论的是TDD…)您不只是更改代码行。添加新功能意味着添加一个或多个新测试。要通过这些测试,您需要更改实现的代码。如果这意味着打破了旧的测试,则意味着一些旧的规范/测试不再有效。首先进行测试是件好事->您现在有机会知道新代码改变了旧的行为。新代码是否打破了旧代码?旧的测试/规范是否不再有效?您是否需要询问您的客户/产品经理“旧规范如何?不再有效?”