我想知道Unittesting和using语句是否真的可以齐头并进,因为无法模拟在using语句中实例化的一次性对象。我如何能够有效地单元测试包含以下using语句的方法?
public void MyMethod() { using(MyDisposableClass disp = new MyDisposableClass()) { ... } }
在进行单元测试时,是否禁止使用语句?
任何评论都表示赞赏。
答案 0 :(得分:4)
不,使用声明当然不是禁止的。但MyDisposableClass实际上做了什么?令我感到震惊的是,这并不是使用语句成为问题的问题 - 这是创建一个你想要模拟的新对象的方法问题 - 那是问题。
你真的需要模拟MyDisposableClass吗?它可以传递到MyMethod而不是在其中创建吗?与以往一样,诀窍是找出如何挂钩进程并在需要时注入自己的对象...
答案 1 :(得分:3)
由于你想模拟资源类,我认为你已经有了
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();
答案 2 :(得分:1)
使用factory pattern和/或dependency injection pattern将大大简化您实例化自己资源的测试方法的单元化方式。
以下是关于这个主题的好读物:
答案 3 :(得分:1)
TypeMock将允许你模拟这个。它的工作原理是动态修改IL,因此可以模拟你无法模拟的东西。
但即使使用TypeMock,你仍然应该看看Jon Skeet和Pop Catalin在上面说的是什么。如果您尝试减少依赖项的数量,则代码将更易于维护。