我最近读到,使类成为单例使不可能模拟该类的对象,这使得测试其客户端变得困难。我无法立即理解其根本原因。有人可以解释一下什么使得模拟单例课程成为不可能吗?另外,使类单例还有其他问题吗?
当然,我可以写一些类似 不使用单例的 东西 ,它们很邪恶,使用Guice / Spring /什么都可以, 但是首先,这不能回答您的问题,其次,当您使用遗留代码 来 处理单例时,例。
因此,我们不要讨论单例的优缺点(这还有另一个问题),而是让我们看看如何在测试过程中处理它们。首先,让我们看一下单例的常见实现:
public class Singleton { private Singleton() { } private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } public static Singleton getInstance() { return SingletonHolder.INSTANCE; } public String getFoo() { return "bar"; } }
这里有两个测试问题:
构造函数是私有的,因此我们不能扩展它(并且我们无法控制测试中实例的创建,但是,这就是单例的重点)。
该getInstance是静态的,所以很难注入假的,而不是单独的对象 使用Singleton的代码 。
getInstance
对于基于继承和多态性的模拟框架,这两点显然都是大问题。如果您可以控制代码,一种选择是通过添加一个setter来使您的单身人士“更具可测试性”,该设置者可以按照学习停止烦恼和热爱单身人士中所述调整内部字段(您甚至不需要嘲笑框架)。如果没有,基于拦截和AOP概念的 现代 模拟框架可以克服前面提到的问题。
例如,模拟静态方法调用显示了如何使用JMockit Expectations模拟Singleton 。
另一种选择是使用PowerMock,它是Mockito或JMock的扩展,它允许模拟通常不可模拟的内容,例如静态,最终,私有或构造方法。您也可以访问类的内部。