[英]How to mock Calendar.getInstance method using JMockit?
我試圖使用JMockit模擬Calendar.getInstance()
方法。 這是我第一次嘲笑任何東西。
下面是我的方法,它以YYYYMMDD
的格式給出了最近一個Monday
或最近Thursday
的日期。
今天是星期天,因此它應該以YYYYMMDD
的格式返回星期四的日期,所以它將是 - 2014027
public static String getCorrectDate() {
Calendar cal = Calendar.getInstance();
try {
int dow = cal.get(Calendar.DAY_OF_WEEK);
switch (dow) {
case Calendar.THURSDAY:
case Calendar.FRIDAY:
case Calendar.SATURDAY:
case Calendar.SUNDAY:
while (cal.get(Calendar.DAY_OF_WEEK) != Calendar.THURSDAY) {
cal.add(Calendar.DATE, -1);
}
break;
case Calendar.MONDAY:
case Calendar.TUESDAY:
case Calendar.WEDNESDAY:
while (cal.get(Calendar.DAY_OF_WEEK) != Calendar.MONDAY) {
cal.add(Calendar.DATE, -1);
}
break;
}
} catch (Exception ex) {
// log error
}
return toDateFormat.format(cal.getTime());
}
所以我的問題是我如何使用JMokcit模擬Calendar.getInstance
方法,這樣我可以輕松地使用junit getCorrectDate
方法?
我以前從未嘲笑它,所以我面臨一些問題?
任何人都可以在我的例子中提供一個簡單的例子嗎?
我試圖這樣做,但它在MockClass
抱怨我,因為它無法解決..我已經添加了JMockit的maven依賴
@MockClass(realClass = Calendar.class)
class CalendarMock {
private int hour;
private int day;
private int minute;
public CalendarMock(int day, int hour, int minute) {
this.hour = hour;
this.day = day;
this.minute = minute;
}
@Mock
public int get(int id) {
if (id == Calendar.HOUR_OF_DAY) {
return hour;
}
if (id == Calendar.DAY_OF_WEEK) {
return day;
}
if (id == Calendar.MINUTE) {
return minute;
}
return -1;
}
}
public class CalendarTest {
@Test
public void testCalender() {
new MockCalendar(1,2,3);
Calendar c = Calendar.getInstance();
int day = c.get(Calendar.HOUR_OF_DAY);
Assert.assertEquals(day, 2);
}
public static class MockCalendar extends MockUp<Calendar> {
private int hour;
private int minute;
private int day;
public MockCalendar(int day, int hour, int minute) {
this.hour = hour;
this.minute = minute;
this.day = day;
}
@Mock
protected void $init() {}
@Mock
public static Calendar getInstance() {
return new GregorianCalendar(1970,1,1);
}
@Mock
public int get(int id) {
if (id == Calendar.HOUR_OF_DAY) {
return hour;
}
if (id == Calendar.DAY_OF_WEEK) {
return day;
}
if (id == Calendar.MINUTE) {
return minute;
}
return -1;
}
}
}
}
你可以增強get邏輯來做東西。
我強烈建議在這些方面引入一個Clock
接口,而不是試圖在這里模擬一個靜態方法:
public interface Clock {
Date now(); // Or long, or Instant if you're using Joda Time
}
然后,您可以擁有一個使用new Date()
或System.currentTimeMillis
的生產實現,以及一個可以設置“當前時間”的測試實現。 將時鍾傳遞給方法,或使其成為實例方法,並使用適當的時鍾“配置”實例(例如,在構造函數中)。
Clock
接口使您的代碼更容易根據我的經驗進行測試,而不必依賴相對高級的模擬功能來模擬靜態方法。
所以你的生產代碼會變成:
public static String getCorrectDate(Clock clock) {
Calendar cal = new GregorianCalendar();
cal.setTimeZone(...); // Which time zone are you interested in?
cal.setTime(clock.now()); // Or cal.setTimeInMillis(clock.now());
// ... logic as before
}
現在,您可以使用許多不同的日期和時間對其進行測試。
這是getCorrectDate()
方法的完整測試類(減去導入),使用JMockit 1.6中提供的兩個getCorrectDate()
API:
public class DateAdjustmentTest
{
final int year = 2014;
final int month = Calendar.MARCH;
final Calendar[] datesOnDifferentWeekdays = {
new GregorianCalendar(year, month, 2), // a sunday
new GregorianCalendar(year, month, 3), // a monday
new GregorianCalendar(year, month, 4), // a tuesday
new GregorianCalendar(year, month, 5), // a wednesday
new GregorianCalendar(year, month, 6), // a thursday
new GregorianCalendar(year, month, 7), // a friday
new GregorianCalendar(year, month, 8), // a saturday
};
@Test
public void getAdjustedDateAccordingToWeekday_usingExpectationsAPI()
{
new NonStrictExpectations(Calendar.class) {{
// Each consecutive call to this method will return the next date.
// Calls to other Calendar methods will not be mocked.
Calendar.getInstance(); result = datesOnDifferentWeekdays;
}};
assertEachDayOfWeekGetsCorrectlyAdjusted();
}
void assertEachDayOfWeekGetsCorrectlyAdjusted()
{
String thursdayOfPreviousWeek = "27/02/2014";
assertEquals(thursdayOfPreviousWeek, getCorrectDate());
String mondayOfSameWeek = "03/03/2014";
assertEquals(mondayOfSameWeek, getCorrectDate());
assertEquals(mondayOfSameWeek, getCorrectDate());
assertEquals(mondayOfSameWeek, getCorrectDate());
String thursdayOfSameWeek = "06/03/2014";
assertEquals(thursdayOfSameWeek, getCorrectDate());
assertEquals(thursdayOfSameWeek, getCorrectDate());
assertEquals(thursdayOfSameWeek, getCorrectDate());
}
@Test
public void getAdjustedDateAccordingToWeekday_usingMockUpAPI()
{
new MockUp<Calendar>() {
@Mock
Calendar getInstance(Invocation inv)
{
return datesOnDifferentWeekdays[inv.getInvocationIndex()];
}
};
assertEachDayOfWeekGetsCorrectlyAdjusted();
}
}
我想說兩個測試都非常簡單,無需更改原始生產代碼。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.