模拟单例类 [英] mocking a singleton class

查看:36
本文介绍了模拟单例类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近读到,使类单例无法模拟该类的对象,这使得测试其客户端变得困难.我无法立即理解根本原因.有人可以解释一下是什么让模拟单例类变得不可能吗?另外,制作类单例还有其他问题吗?

I recently read that making a class singleton makes it impossible to mock the objects of the class, which makes it difficult to test its clients. I could not immediately understand the underlying reason. Can someone please explain what makes it impossible to mock a singleton class? Also, are there any more problems associated with making a class singleton?

推荐答案

当然,我可以写一些类似不要使用单例,它们是邪恶的,使用 Guice/Spring/whatever 但首先,这不会回答您的问题,其次,您有时必须处理单例,例如在使用遗留代码时.

Of course, I could write something like don't use singleton, they are evil, use Guice/Spring/whatever but first, this wouldn't answer your question and second, you sometimes have to deal with singleton, when using legacy code for example.

所以,我们不讨论单身人士的好与坏(还有另一个问题 为此)但让我们看看如何在测试期间处理它们.首先,让我们看一下单例的常见实现:

So, let's not discuss the good or bad about singleton (there is another question for this) but let's see how to handle them during testing. First, let's look at a common implementation of the singleton:

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";
    }
}

这里有两个测试问题:

  1. 构造函数是私有的,因此我们无法扩展它(并且我们无法控制测试中实例的创建,但这就是单例的重点).

  1. The constructor is private so we can't extend it (and we can't control the creation of instances in tests but, well, that's the point of singletons).

getInstance 是静态的,因此很难在使用单例的代码中注入假的而不是单例对象.

The getInstance is static so it's hard to inject a fake instead of the singleton object in the code using the singleton.

对于基于继承和多态的mocking框架,这两点显然都是大问题.如果您可以控制代码,一种选择是使您的单例更易于测试".通过添加允许调整内部字段的设置器,如 学会停止担心并热爱单身(在这种情况下,您甚至不需要模拟框架).如果不这样做,现代基于拦截和 AOP 概念的模拟框架可以克服前面提到的问题.

For mocking frameworks based on inheritance and polymorphism, both points are obviously big issues. If you have the control of the code, one option is to make your singleton "more testable" by adding a setter allowing to tweak the internal field as described in Learn to Stop Worrying and Love the Singleton (you don't even need a mocking framework in that case). If you don't, modern mocking frameworks based on interception and AOP concepts allow to overcome the previously mentioned problems.

例如,模拟静态方法调用展示了如何使用 JMockit Expectations.

For example, Mocking Static Method Calls shows how to mock a Singleton using JMockit Expectations.

另一种选择是使用 PowerMock,它是 Mockito 的扩展或 JMock 允许模拟通常不可模拟的东西,如静态、最终、私有或构造函数方法.您还可以访问类的内部.

Another option would be to use PowerMock, an extension to Mockito or JMock which allows to mock stuff normally not mock-able like static, final, private or constructor methods. Also you can access the internals of a class.

这篇关于模拟单例类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆