如何使用静态方法进行模拟?

时间:2008-09-30 13:38:54

标签: c# .net mocking interface static-methods

我是模拟对象的新手,但我知道我需要让我的类实现接口才能模拟它们。

我遇到的问题是,在我的数据访问层,我想要静态方法,但我不能在接口中放置静态方法。

最好的方法是什么?我应该只使用实例方法(这似乎是错误的)还是有其他解决方案?

7 个答案:

答案 0 :(得分:26)

是的,您使用实例方法。静态方法基本上说,“有一种方法可以实现这个功能 - 它不是多态的。”模拟依赖于多态性。

现在,如果您的静态方法在逻辑上不关心您正在使用的实现,那么它们可能能够将接口作为参数,或者可能在没有与状态交互的情况下工作 - 但是否则您应该使用实例(可能还有依赖注入将所有东西连接在一起)。

答案 1 :(得分:26)

我找到了一个blog via google,其中包含一些很好的示例:

  1. 将类重构为实例类并实现接口。

    您已经说明了您不想这样做。

  2. 使用包含静态类成员

    的委托的包装器实例类

    这样做可以通过代表模拟静态界面。

  3. 使用包含受保护成员的包装器实例类来调用静态类

    这可能是最简单的模拟/管理而不重构,因为它可以继承和扩展。

答案 2 :(得分:22)

我会使用方法对象模式。有一个静态实例,并在静态方法中调用它。应该可以子类化测试,具体取决于你的模拟框架。

即。在您的类中使用静态方法有:

private static final MethodObject methodObject = new MethodObject();

public static void doSomething(){
    methodObject.doSomething();
}

并且您的方法对象可以非常简单,易于测试:

public class MethodObject {
    public void doSomething() {
        // do your thang
    }
}

答案 3 :(得分:5)

你可能试图在一个起点太深的地方进行测试。不需要创建测试来单独测试每个方法;私有和静态方法应该通过调用公共方法来测试,然后依次调用私有方法和静态方法。

所以我们说你的代码是这样的:

public object GetData()
{
 object obj1 = GetDataFromWherever();
 object obj2 = TransformData(obj1);
 return obj2;
} 
private static object TransformData(object obj)
{
//Do whatever
}

您不需要针对TransformData方法编写测试(并且您不能)。而是为GetData方法编写测试,测试TransformData中完成的工作。

答案 4 :(得分:4)

尽可能使用实例方法。

使用公共静态Func [T,U](可替代模拟函数的静态函数引用),其中不可能使用实例方法。

答案 5 :(得分:0)

一个简单的解决方案是允许通过setter更改静态类的实现:

class ClassWithStatics {

  private IClassWithStaticsImpl implementation = new DefaultClassWithStaticsImpl();

  // Should only be invoked for testing purposes
  public static void overrideImplementation(IClassWithStaticsImpl implementation) {
     ClassWithStatics.implementation = implementation;
  }

  public static Foo someMethod() {
    return implementation.someMethod();
  }

}

因此,在测试设置中,您使用一些模拟接口调用overrideImplementation。好处是您不需要更改静态类的客户端。缺点是你可能会有一些重复的代码,因为你必须重复静态类的方法和它的实现。但有时静态方法可以使用提供基本功能的ligther接口。

答案 6 :(得分:0)

您遇到的问题是当您使用第三方代码时,它是从您的某个方法调用的。我们最终做的是将它包装在一个对象中,并使用dep inj调用它,然后你的单元测试可以模拟第三方静态方法用它调用setter。