为什么单身人士课很难测试?

有效的Java项目3(使用私有构造函数或枚举类型强制执行singleton属性)注意到:

将一个类作为一个单例可能会使得测试它的客户端变得困难,因为除非它实现了一个用作其类型的接口,否则不可能将一个模拟实现替换为单例。

为了测试目的,为什么仅仅实例化一个单例实例并测试它的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;
    }

}

你可以将它作为一个依赖注入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());
}
链接地址: http://www.djcxy.com/p/78797.html

上一篇: Why is a singleton class hard to test?

下一篇: Singleton and unit testing