我有一些代码执行一些遗留的“数据库”操作,然后处理结果。我想编写一个单元测试来检查调用遗留代码的方法,而不与“数据库”进行交互。
我的代码看起来像这样:
public static bool CallRoutine(LegacySession session, /* routine params*/)
{
try
{
LegacyRoutine routine = session.CreateRoutine(/* routine params */);
routine.Call();
// Process result
}
catch (LegacyException ex)
{
// Perform error handling
}
}
如果这是我的所有代码,我将创建LegacySession
和LegacyRoutine
实现的接口,然后使用MOQ或类似的东西编写使用这些接口的模拟实现的单元测试。问题是我无法访问LegacyRoutine
或LegacySession
的代码,因此我无法让它们实现接口。
关于如何在不改变生产代码的情况下做到这一点的任何想法?
答案 0 :(得分:5)
如果您无法访问 LegacyRoutine (我猜它在引用的DLL中),为什么不为它创建一个包装器,然后轻弹/关闭不同的实现:
public interface ILegacyWrapper
{
ILegacyRoutine CreateRoutine();
// etc etc
}
public interface ILegacyRoutine
{
// put members of LegacyRoutine
}
知道我的意思吗?只需将所有内容都模拟为包装器/接口。
然后你可以去:
ILegacyRoutine routine = session.CreateRoutine(/* routine params */)
会话将被声明为 ILegacyWrapper ,但是使用模拟具体实现。
此外,不言而喻(但无论如何我会说),你应该考虑一个DI框架,让你的生活更简单。否则,你将以IFoo foo = new Foo()
(硬编码注射)结束。
StructureMap是我选择的DI毒药。
HTH
答案 1 :(得分:1)
您可以在其 具有接口的API上编写一个瘦包装器。这是否是一个实际的事情取决于API的大小。
答案 2 :(得分:0)
搜索C#模拟具体类型。对不起,我必须运行,但这里是我发现的第一件可以解决问题的链接(可能有更好的解决方案,但看起来还不错):
http://docs.typemock.com/isolator/##typemock.chm/Documentation/CreatingFakesWithAAA.html
另外,查看Moq,我在过去取得了很大的成功
答案 3 :(得分:0)
我建议你使用依赖注入框架。它可以帮助您通过将外部类依赖性分解为注入到类中的对象来使您的类更松散地进行复制。这些对象通常由接口表示,它可以帮助您在生产和测试时使用不同的实现。这样,您在测试时就不必实际调用外部数据库。我可以推荐Ninject。这使得依赖注入比手动执行更容易。