gpt4 book ai didi

java - 为什么单例类很难测试?

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:43:24 25 4
gpt4 key购买 nike

Effective Java 第 3 项(使用私有(private)构造函数或枚举类型实现单例属性)指出:

Making a class a singleton can make it difficult to test its clients, as it's impossible to substitute a mock implementation for a singleton unless it implements an interface that serves as its type.

出于测试目的,为什么仅实例化一个单例实例并测试其 API 是不够的?那不是客户会消费的东西吗?引用似乎暗示测试单例将涉及“模拟实现”,但为什么有必要这样做?

我看到过各种“解释”,它们或多或少是对上述引述的改写。有人可以进一步解释这一点,最好是用代码示例吗?

最佳答案

如果您的单例正在对数据库执行操作或将数据写入文件怎么办?您不希望在单元测试中发生这种情况。您可能希望模拟该对象以在内存中执行一些操作,这样您就可以验证它们而不会产生永久的副作用。单元测试应该是独立的,不应创建与数据库的连接或与外部系统执行其他可能失败的操作,然后由于不相关的原因导致单元测试失败。

使用伪 java 的示例(我是 C# 开发人员):

public class MySingleton {

private static final MySingleton instance = new MySingleton();

private MySingleton() { }

public int doSomething() {
//create connection to database, write to a file, etc..
return something;
}

public static MySingleton getInstance() {
return instance;
}
}

public class OtherClass {

public int myMethod() {
//do some stuff
int result = MySingleton.getInstance().doSomething();

//do some other suff
return something;
}
}

为了测试myMethod,我们必须进行实际的数据库调用、文件操作等

@Test
public void testMyMethod() {
OtherClass obj = new OtherClass();

//if this fails it might be because of some external code called by
//MySingleton.doSomething(), not necessarily the logic inside MyMethod()

Asserts.assertEqual(1, obj.myMethod());
}

如果 MySingleton 是这样的:

public class MyNonSingleton implements ISomeInterface {

public MyNonSingleton() {}

@Override
public int doSomething() {
//create connection to database, write to a file, etc..
return something;
}

}

然后您可以像这样将它作为依赖注入(inject)到 MyOtherClass 中:

public class OtherClass {

private ISomeInterface obj;

public OtherClass(ISomeInterface obj) {
this.obj = obj;
}

public int myMethod() {
//do some stuff
int result = obj.doSomething();

//do some other stuff
return something;
}
}

然后你可以这样测试:

@Test
public void TestMyMethod() {
OtherClass obj = new OtherClass(new MockNonSingleton());

//now our mock object can fake the database, filesystem etc. calls to isolate the testing to just the logic in myMethod()

Asserts.assertEqual(1, obj.myMethod());
}

关于java - 为什么单例类很难测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25273210/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com