java.util.Date 的可模拟帮助器类
我想要一个帮助类来获取当前日期。由于未来的测试问题(可能需要返回与系统时间不同的时间),我想避免在代码中使用 new Date()
,并且我无法使用 JodaTime 来防止测试问题。
我正在考虑这样的助手:
public interface DateHelper {
/**
* Returns the current date.
*/
Date now();
}
但是我如何向客户提供这个界面的模拟呢? 我能想到的唯一解决方案是:
public ClientOfDateHelper {
private DateHelper dateHelper;
// no-arg constructor that instantiates a standard implementation of DateHelper
public ClientOfDateHelper() {
this.dateHelper = new DefaultDateHelper();
}
// constructor that can be used to pass mock to the client
public ClientOfDateHelper(DateHelper suppliedDateHelper) {
this.dateHelper = suppliedDateHelper;
}
public void foo() {
Date today = dateHelper.now();
// do some work that requires today's date
}
}
是否有更优雅的解决方案,需要更少的代码来使用 DateHelper,但它允许使用模拟?
I'd like to have a helper class for getting the current date. I want to avoid having new Date()
in code because of future testing issues (may need to return different time than system time) and I cannot use JodaTime to prevent the problem with testing.
I was thinking of a helper like this:
public interface DateHelper {
/**
* Returns the current date.
*/
Date now();
}
But how can I supply mocks of this interface to the clients?
The only solution I can think of is this:
public ClientOfDateHelper {
private DateHelper dateHelper;
// no-arg constructor that instantiates a standard implementation of DateHelper
public ClientOfDateHelper() {
this.dateHelper = new DefaultDateHelper();
}
// constructor that can be used to pass mock to the client
public ClientOfDateHelper(DateHelper suppliedDateHelper) {
this.dateHelper = suppliedDateHelper;
}
public void foo() {
Date today = dateHelper.now();
// do some work that requires today's date
}
}
Is there a more elegant solution that requires less code to use the DateHelper, yet it allows using mocks?
易于测试是依赖注入的好处之一。使用像 Spring 这样的框架允许您从外部配置依赖项。因此,您的实现将使用您的 spring 配置运行,并且您的单元测试将使用您通过构造函数或属性设置器提供的模拟运行。这消除了对上述两个构造函数的需要,您只需使用一个接受 DateHelper 的构造函数。
Ease of testing is one of the benefits of dependency injection. Using a framework like Spring allows you to externally configure your dependencies. So your implementation will run with your spring configuration, and your unit tests will run with the mocks you supply through constructor or property setters. This eliminates the need for the two constuctors above, you would just use one that accepts DateHelper.