[英]java: how to mock Calendar.getInstance()?
In my code I have something like this:在我的代码中,我有这样的东西:
private void doSomething() {
Calendar today = Calendar.getInstance();
....
}
How can I "mock" it in my junit test to return a specific date?如何在我的 junit 测试中“模拟”它以返回特定日期?
You can mock it using PowerMock in combination with Mockito: 你可以使用PowerMock和Mockito一起模拟它:
On top of your class: 在课堂上:
@RunWith(PowerMockRunner.class)
@PrepareForTest({ClassThatCallsTheCalendar.class})
The key to success is that you have to put the class where you use Calendar in PrepareForTest instead of Calendar itself because it is a system class. 成功的关键是你必须将类放在PrepareForTest中使用Calendar而不是Calendar本身,因为它是一个系统类。 (I personally had to search a lot before I found this)
(在我发现这个之前,我个人不得不经常搜索)
Then the mocking itself: 然后是嘲弄本身:
mockStatic(Calendar.class);
when(Calendar.getInstance()).thenReturn(calendar);
As far as I see it you have three sensible options: 据我所知,你有三个合理的选择:
Inject the Calendar
instance in whatever method/class you set that day in. 以您在当天设置的任何方法/类中注入
Calendar
实例。
private void method(final Calendar cal) { Date today = cal.getTime(); }
Use JodaTime instead of Calendar
. 使用JodaTime而不是
Calendar
。 This is less an option and more a case of a suggestion as JodaTime will make your life a lot easier. 这不是一个选择,而是一个建议的案例,因为JodaTime将使您的生活更轻松。 You will still need to inject this time in to the method.
您仍需要将此时间注入方法。
DateTime dt = new DateTime();
Date jdkDate = dt.toDate();
Wrap Calendar
inside some interface that allows you to fetch the time. 在一些允许您获取时间的界面中包装
Calendar
。 You then just mock that interface and get it to return a constant Date
. 然后,您只需模拟该接口并使其返回一个常量
Date
。
Date today = calendarInterfaceInstance.getCurrentDate()
Don't mock it - instead introduce a method you can mock that gets dates. 不要嘲笑它 - 而是引入一个你可以模拟得到日期的方法。 Something like this:
像这样的东西:
interface Utility {
Date getDate();
}
Utilities implements Utility {
public Date getDate() {
return Calendar.getInstance().getTime();
}
}
Then you can inject this into your class or just use a helper class with a bunch of static methods with a load method for the interface: 然后你可以将它注入到你的类中,或者只使用带有一堆静态方法的helper类和一个load方法:
public class AppUtil {
private static Utility util = new Utilities();
public static void load(Utility newUtil) {
this.util = newUtil;
}
public static Date getDate() {
return util.getDate();
}
}
Then in your application code: 然后在您的应用程序代码:
private void doSomething() {
Date today = AppUtil.getDate();
....
}
You can then just load a mock interface in your test methods. 然后,您可以在测试方法中加载模拟接口。
@Test
public void shouldDoSomethingUseful() {
Utility mockUtility = // .. create mock here
AppUtil.load(mockUtility);
// .. set up your expectations
// exercise the functionality
classUnderTest.doSomethingViaAPI();
// ... maybe assert something
}
See also Should you only mock types you own? 另请参阅您是否只能模拟您拥有的类型? and Test smell - everything is mocked
和测试气味 - 一切都被嘲笑
Using Mockito and PowerMockito: 使用Mockito和PowerMockito:
Calendar endOfMarch = Calendar.getInstance();
endOfMarch.set(2011, Calendar.MARCH, 27);
PowerMockito.mockStatic(Calendar.class);
Mockito.when(Calendar.getInstance()).thenReturn(endOfMarch);
Write a class called DateHelper
with a method getCalendar
that returns Calendar.getInstance()
. 编写一个叫做类
DateHelper
与方法getCalendar
返回Calendar.getInstance()
Refactor the class that you're testing so that it has a member variable of type DateHelper
, and a constructor that injects that member variable. 重构您正在测试的类,使其具有
DateHelper
类型的成员变量,以及注入该成员变量的构造函数。 Use that constructor in your test, to inject a mock of DateHelper
, in which getCalendar
has been stubbed to return some known date. 使用该构造在您的测试,注入的模拟
DateHelper
,其中getCalendar
已存根返回一些已知的日期。
You can mockit using JMockit. 你可以使用JMockit进行模拟。 Here you can see how you can do it: Mock Java Calendar - JMockit vs Mockito .
在这里,您可以看到如何做到这一点: 模拟Java日历 - JMockit与Mockito 。
Avoid use Calendar.getInstance()
and just use Mockito
methods to return what you like.避免使用
Calendar.getInstance()
并仅使用Mockito
方法返回您喜欢的内容。 For example:例如:
@Test
fun italianLocale_returnsItalianFormatDate() {
val calendar: Calendar = Mockito.mock(Calendar::class.java)
Mockito.`when`(calendar.get(Calendar.DAY_OF_MONTH)).thenReturn(27)
Mockito.`when`(calendar.get(Calendar.YEAR)).thenReturn(2023)
Mockito.`when`(calendar.get(Calendar.MONTH)).thenReturn(1)
val formatted = calendar.toReadableDate()
assert(formatted == "27/01/2023")
}
import Mockito in your gradle file with:在您的 gradle 文件中导入 Mockito:
testImplementation ("org.mockito.kotlin:mockito-kotlin:x.x.x")
or (if you are using groovy)或者(如果你使用的是 groovy)
testImplementation "org.mockito.kotlin:mockito-kotlin:x.x.x"
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.