2010-03-09 96 views
2

这似乎是一个很容易的问题,但我似乎无法找到关键字来影响我的搜索。moqing静态方法调用c#库类

我试图通过嘲笑此方法调用内的所有对象进行单元测试。我能够这样做的都是我自己创作的,除了这一个:

public void MyFunc(MyVarClass myVar) 
{ 
    Image picture; 
    ... 

    picture = Image.FromStream(new MemoryStream(myVar.ImageStream)); 

    ... 
} 

FromStream从图像类的静态调用(C#的一部分)。所以我怎么能重构我的代码来嘲笑这一点,因为我真的不想提供一个图像流到单元测试。

回答

1

您可以将静态函数包装到Func类型属性中,该属性可以通过单元测试使用模拟或存根来设置。

public class MyClass 
{ 
    .. 

    public Func<Image, MemoryStream> ImageFromStream = 
            (stream) => Image.FromStream(stream); 


    public void MyFunc(MyVarClass myVar) 
    { 
     ... 

     picture = ImageFromStream(new MemoryStream(myVar.ImageStream)); 

     ... 
    } 


    .. 
} 
+0

我觉得像包装到一个界面的想法,如果我有多个静态调用实例通过我的代码,此解决方案不能很好地扩展。 我将不得不为每个静态调用创建一个函数。有没有办法模拟库类的静态方法? – Joe 2010-03-09 06:41:26

+0

您只需要为不同的静态方法创建一个属性,因为您可以重复使用它们。我相信TypeMock可以使用一些IL编织来嘲弄静态方法,但它不是免费的。解耦代码是可测试的,在C#中恐怕需要很多工作。 – tarn 2010-03-09 06:47:41

+0

经过一番思考,提供的界面和功能解决方案都很混乱,但是这个功能解决方案比创建一个新界面和类仅仅嘲弄一个静态功能花费更少的线。所以我正在用这个。感谢所有的答案。 – Joe 2010-03-10 01:35:44

3

您可以创建一个IImageLoader接口。 “正常”实现只是调用Image.FromStream,而您的单元测试版本可以做任何您需要的操作。

+0

这将意味着我不得不为每一个静态方法调用我会想办法让不同类别的接口。 我希望有一个更优雅的方式来做到这一点...... – Joe 2010-03-09 06:37:44

+1

不,没有优雅的方式来解决这个静态编译语言没有运行时帮助。有一种方法可以通过访问分析CLR API(非常复杂)来完成此操作。这就是TypeMock的工作原理 – CVertex 2010-03-09 06:46:08

+1

除了CVertex使用TypeMock的解决方案之外,确实没有办法。静态方法和单元测试并不能很好地结合在一起。 – 2010-03-09 06:47:53

2

Moq和大多数其他模拟框架不支持嘲笑静态方法。然而,TypeMock确实支持嘲笑静态方法,如果您愿意购买它,可能会对您感兴趣。否则,你将不得不重构,以便可以模拟一个接口...

+0

MSR的痣也在这个空间中发挥作用 – 2010-03-10 13:47:25

1

这可以通过Moles,一个Visual Studio 2010电动工具来实现。该Moles代码应该是这样的:

// replace Image.FromStream(MemoryStream) with a delegate 
MImage.FromStreamMemoryStream = stream => null;