在不更改应用程序代码的情

时间:2013-02-25 14:19:30

标签: java scala testing mocking

首先,我使用Scala,但任何Java方法都可以。 (我将使用Java代码作为示例,以便更容易理解。)

说我有一个Connection界面及其实施RealConnectionFakeConnection

我想在我的应用程序中包含两个条目:一个发布条目和一个测试条目。我希望像平常一样编写我的应用程序代码,然后开始使用发布版本所有类的测试,但有一个例外,它使用FakeConnection代替RealConnection

我的应用程序通过Connection.get()访问连接。

我不想要的是这样的:

public static Connection get() {
    if ( isReleaseVersion )
        return new RealConnection();
    return new FakeConnection();
}

我希望我的应用程序代码不会被这种代码污染。

有一个Config对象是可能的,如:

public static Connection get() {
    return Config.getConnectionFactory().get();
}

这里的问题是我每次要测试时都需要更改Config课程。如果没有其他方法,我可能会使用这种方法。

我不想使用的是定制者。我想处理final变量或函数!不是这样的:

public class TestEntry {
    public static void main(String... args) }
        Config.connectionFactory = new FakeConnectionFactory();
        Config.databaseConnection = new FakeDatabaseConnection(); // Singleton, no factory needed.
        MyApplication.start(args); // the ReleaseEntry is somewhere else!
    }
}

我不想使用的是Guice。每次我想做测试时,我都必须重新定义我的模块。另外,我不想在Scala中使用它。

Reflection是可能的,但错误只会出现在运行时,所以它不是很好。

有没有其他选择来实现我的目标?

我是否必须采用Config方式?

问候。

1 个答案:

答案 0 :(得分:1)

你的问题包含矛盾:

您希望全球可用

  

我的应用程序通过Connection

访问Connection.get()

未使用变量

存储
  

我不想使用的是定制者。我想处理最终变量或函数!

但是你想在运行时提供这个实现。

其他人提到“依赖注入”是一种“控制倒置”的形式,你问题中的要求告诉我这就是你想要的。

如果您不想使用变量,则必须使用连接将正确的实例传递给组件。使用Scala,您可以选择将其传递给implicitly而不是explicitly

class MyComponent(name:String)(implicit c:Configuration)

implicit val configuration = new TestConfiguration

//note that the configuration is passed in implicitly
val m = new MyComponent("foo")

此要求也使其他选项变得棘手:

  

反射是可能的,但错误只会出现在运行时

如果您不想更改任何要求,您可能(理论上)可以使用Scala宏等方法来执行此操作。如果这就是你想要的,我建议你创建一个新问题。