Question

I am trying to mock Calendar.getInstance() method using JMockit. This is the first time I am mocking anything.

Below is my method which gives me the date of either recent Monday or recent Thursday in the format of YYYYMMDD.

Today is Sunday, so it should return date for Thursday in the format of YYYYMMDD so it will be - 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());
}

So my question is how do I mock the Calendar.getInstance method using JMokcit so that I can easily junit getCorrectDate method?

I have never mocked it before so I am facing some problem?

Can anyone provide a simple example if possible on my example?

I am trying to do it like this but it is complaining me on MockClass as it is not able to resolve.. I have added the maven dependency of JMockit as well

@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;
 }
}

No correct solution

OTHER TIPS

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;
        }
    }
 }

}

you can enhance the get logic to do stuff.

Rather than try to mock a static method here, I would strongly recommend introducing a Clock interface along these lines:

public interface Clock {
    Date now(); // Or long, or Instant if you're using Joda Time
}

Then you can have a production implementation which uses new Date() or System.currentTimeMillis, and a test implementation where you can set "the current time". Pass your clock to the method, or make it an instance method and "configure" the instance (e.g. in the constructor) with the appropriate clock.

The Clock interface makes your code much simpler to test in my experience, without having to rely on relatively advanced mocking features for mocking static methods.

So your production code would become something like:

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
}

Now you can test that with lots of different dates and times.

Here is a complete test class (minus imports) for the getCorrectDate() method, using the two mocking APIs available in JMockit 1.6:

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();
    }
}

I would say both tests are quite simple, without having to change the original production code.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top