我想知道单元测试和 using 语句是否真的可以齐头并进,因为没有办法模拟在 using 语句中实例化的一次性对象。我如何能够有效地对包含以下 using 语句的方法进行单元测试?
公共无效我的方法() { 使用(MyDisposableClass disp = new MyDisposableClass()) { ... } }
当您进行单元测试时,是否完全禁止使用语句?
任何意见表示赞赏。
我想知道单元测试和 using 语句是否真的可以齐头并进,因为没有办法模拟在 using 语句中实例化的一次性对象。我如何能够有效地对包含以下 using 语句的方法进行单元测试?
公共无效我的方法() { 使用(MyDisposableClass disp = new MyDisposableClass()) { ... } }
当您进行单元测试时,是否完全禁止使用语句?
任何意见表示赞赏。
不,当然不禁止使用语句。但是 MyDisposableClass 实际上做了什么?令我震惊的是,这实际上并不是 using 语句成为问题的问题-而是创建要模拟的新对象的方法问题-这就是问题所在。
你真的需要模拟 MyDisposableClass 吗?它可以传递给 MyMethod 而不是在其中创建吗?与以往一样,诀窍是弄清楚如何在需要时加入进程并注入自己的对象......
由于您想模拟资源类,我假设您已经拥有
interface IResource : IDisposable
{
void DoSomething();
}
class DisposableResource : IResource
{
public void Dispose() { Console.WriteLine("That's it. I'm outta here!"); }
public void DoSomething() { Console.WriteLine("Hard work this"); }
}
为了能够注入 obj,您需要一个接缝.. 即 GetResource()
class MyClass
{
protected virtual IResource GetResource()
{
return new DisposableResource();
}
public void MyMethod1()
{
using (IResource r = GetResource())
{
r.DoSomething();
}
}
}
在您的测试代码中,只需子类化并覆盖 GetResource() 即可返回一个模拟。
class MySubClassForTest : MyClass
{
protected override IResource GetResource()
{
return new MockResource();
}
}
class MockResource : IResource // or use a mock framework to create one
{
public void DoSomething() { Console.WriteLine("Me work?"); }
public void Dispose() { Console.WriteLine("Disposed Mock!"); }
}
而已。
MyClass obj = new MyClass(); // production code
obj.MyMethod1();
obj = new MySubClassForTest(); // test code
obj.MyMethod1();
TypeMock 将允许你模拟它。它通过动态修改 IL 来工作,因此在模拟你无法模拟的东西时没有问题。
但即使使用 TypeMock,您仍然应该看看 Jon Skeet 和 Pop Catalin 上面所说的内容。如果您尝试减少依赖项的数量,您的代码将更易于维护。