0

我一直以这种方式测试 Dates,在我的类中有一个受保护的方法 getDate(),我已经覆盖了它以用于测试目的。例子:

public class MyClass {
    protected Date getDate(){
        return new Date();
    };
}

测试:

MyClass myclass = new MyClass(){
    @Override
    protected Date getDate(){ 
        return new Date(1234567890);
    }
};

这到今天已经足够了,但是出现了以下问题:我有一个想要实例化一次的类,所以我使用单例模式:

public static Something getInstance() {
    if (instance == null) {
        instance = new Something();
    }

    return instance;
}

问题是我必须以这种方式创建一个对象:Something.getInstance() - 对象是在该方法内创建的。我无法覆盖 getInstance 中的 getDate 方法,因为它没有意义(有时我需要真实实例,有时需要测试实例)。这引出了一个问题:在这种情况下如何测试日期?

4

4 回答 4

1

正如您刚刚注意到的,每次使用普通 Java 单例时,都会创建无法测试的代码。

还有其他方法可以只拥有一个类的一个实例。从简单 - 只需创建一次 :) 到使用 Spring 等 IoC 框架让他们关心它。

我建议你看一下Misko Hevery 的编写可测试代码指南,关于全局状态的部分。

于 2013-03-28T09:49:31.347 回答
1

当且仅当单例模式不能不惜一切代价避免时,您可以模拟Something使用Powermock模拟类的构造:

//create mock instance,     
Something mockSomethingInstance = createMock(Something.class);
//create your Date instance to return
Date d = new Date();
when(mockSomethingInstance.getDate()).thenReturn(d);

您必须模拟 Something 类的构造函数,以始终返回您创建的实例(当心,这样做也会覆盖Something该类的所有其他构造,但在这种情况下,因为这是一个单例,它似乎没问题。) :

expectNew(Something.class).andReturn(mockSomethingInstance); 

此外,Powermock 也可以模拟静态函数调用,因此您也可以模拟类上的 getInstance 函数Something

//mock the static functions
mockStatic(Something.class);          

expect(Something.getInstance()).andReturn(mockSomethingInstance);
//have to replay the class in order to work
replay(IdGenerator.class); 

但是,我假设您想要进行部分模拟,因为您想要测试类本身的行为。但这开始变得越来越丑陋......

总而言之:在使用 Singletons 之前三思而后行——它们看起来很简单(当然,onlz 看起来......),从长远来看,它们很快就会变成噩梦......使用 Spring 是一种更清洁的方式,省去了很多麻烦。

于 2013-03-28T09:49:57.110 回答
0

如果你在你的单例上放置一个 getDate() 方法,那么它就有所谓的全局状态,这使得几乎不可能为测试目的进行模拟。您唯一的选择是使用测试框架,或者将您的类更改为不是“真正的”单例,同时以其他方式确保只能实例化它的一个实例。我认为后一种选择是正确的方法,在这种情况下你不应该使用单例。

于 2013-03-28T09:49:19.667 回答
0

您需要使用 Capture 听起来很多(假设 EasyMock 是一个选项)。

于 2013-03-28T09:46:31.673 回答