单元测试包含using语句的方法

时间:2008-12-11 10:22:10

标签: .net unit-testing dispose

我想知道Unittesting和using语句是否真的可以齐头并进,因为无法模拟在using语句中实例化的一次性对象。我如何能够有效地单元测试包含以下using语句的方法?

public void MyMethod()
{
   using(MyDisposableClass disp = new MyDisposableClass())
   {
       ...
   }
}

在进行单元测试时,是否禁止使用语句?

任何评论都表示赞赏。

4 个答案:

答案 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在上面说的是什么。如果您尝试减少依赖项的数量,则代码将更易于维护。