Ant*_*ram 7 c# unit-testing dependency-injection
假设遗留类和方法结构如下所示
public class Foo
{
public void Frob(int a, int b)
{
if (a == 1)
{
if (b == 1)
{
// does something
}
else
{
if (b == 2)
{
Bar bar = new Bar();
bar.Blah(a, b);
}
}
}
else
{
// does something
}
}
}
public class Bar
{
public void Blah(int a, int b)
{
if (a == 0)
{
// does something
}
else
{
if (b == 0)
{
// does something
}
else
{
Baz baz = new Baz();
baz.Save(a, b);
}
}
}
}
public class Baz
{
public void Save(int a, int b)
{
// saves data to file, database, whatever
}
}
Run Code Online (Sandbox Code Playgroud)
然后假设管理层发出一项模糊的任务,对我们所做的每件新事物执行单元测试,无论是增加的功能,修改的需求还是错误修复.
我可能是文字解释的坚持者,但我认为"单元测试"这个短语意味着什么.例如,这并不意味着给定1和2的输入,Foo.Frob只有当1和2保存到数据库时,单元测试应该成功.基于我所读到的内容,我认为它最终意味着基于1和2的输入,Frob被调用Bar.Blah.是否Bar.Blah做了应该做的事情不是我直接关注的问题.如果我关心测试整个过程,我相信还有另一个术语,对吗?功能测试?场景测试?随你.如果我太僵硬,请纠正我,拜托!
坚持我刚才的严格解释,让我们假设我想尝试利用依赖注入,一个好处是我可以模拟我的类,以便我可以,例如,我不能将我的测试数据保存到数据库或文件或无论情况如何.在这种情况下,Foo.Frob需求IBar,IBar需求IBaz,IBaz可能需要一个数据库.注入这些依赖项在哪里?进Foo?或Foo仅仅需要IBar,然后Foo负责创建一个实例IBaz?
当您进入这样的嵌套结构时,您可以快速看到可能存在多个必需依赖项.进行这种注射的首选方法是什么?
让我们从你的上一个问题开始.注入的依赖项在哪里:一种常见的方法是使用构造函数注入(如Fowler所述).所以在构造函数中Foo注入了一个IBar.具体实现的IBar,Bar反过来的IBaz注入它的构造.最后,IBazimplementation(Baz)有一个IDatabase(或其他)注入.如果您使用诸如Castle Project之类的DI框架,您只需要求DI容器Foo为您解析一个实例.然后,它将使用您配置的任何内容来确定IBar您正在使用的实现.如果它确定你的实现IBar是Bar然后它将确定IBaz您正在使用的实施,等等.
这种方法给你的是,你可以单独测试每个具体的实现,并检查它是否正确调用(模拟)抽象.
为了评论你对过于严格等问题的担忧,我唯一可以说的是,在我看来,你正在选择正确的道路.也就是说,当实施所有这些测试的实际成本变得明显时,管理层可能会感到意外.
希望这可以帮助.
| 归档时间: |
|
| 查看次数: |
2739 次 |
| 最近记录: |