我是模拟对象的新手,但我知道我需要让我的类实现接口才能模拟它们。
我遇到的问题是,在我的数据访问层,我想要静态方法,但我不能在接口中放置静态方法。
最好的方法是什么?我应该只使用实例方法(这似乎是错误的)还是有其他解决方案?
答案 0 :(得分:26)
是的,您使用实例方法。静态方法基本上说,“有一种方法可以实现这个功能 - 它不是多态的。”模拟依赖于多态性。
现在,如果您的静态方法在逻辑上不关心您正在使用的实现,那么它们可能能够将接口作为参数,或者可能在没有与状态交互的情况下工作 - 但是否则您应该使用实例(可能还有依赖注入将所有东西连接在一起)。
答案 1 :(得分:26)
我找到了一个blog via google,其中包含一些很好的示例:
将类重构为实例类并实现接口。
您已经说明了您不想这样做。
使用包含静态类成员
的委托的包装器实例类这样做可以通过代表模拟静态界面。
使用包含受保护成员的包装器实例类来调用静态类
这可能是最简单的模拟/管理而不重构,因为它可以继承和扩展。
答案 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。