如果您的单例正在对数据库执行操作或将数据写入文件怎么办?您不希望在单元测试中发生这种情况。您可能希望模拟对象以在内存中执行一些操作,这样您就可以验证它们而不会产生永久的副作用。单元测试应该是自包含的,不应创建与数据库的连接或与外部系统执行其他可能失败的操作,然后导致单元测试由于不相关的原因而失败。
伪 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;
}
}
然后你可以像这样将它作为依赖注入到 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());
}