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?
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?
As far as I see it you have three sensible options:
Inject the Calendar instance in whatever method/class you set that day in.
private void method(final Calendar cal) { Date today = cal.getTime(); }
Use JodaTime instead of Calendar. This is less an option and more a case of a suggestion as JodaTime will make your life a lot easier. 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. You then just mock that interface and get it to return a constant 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:
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
You can mock it using PowerMock in combination with 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. (I personally had to search a lot before I found this)
Then the mocking itself:
mockStatic(Calendar.class); when(Calendar.getInstance()).thenReturn(calendar); Using Mockito and PowerMockito:
Calendar endOfMarch = Calendar.getInstance(); endOfMarch.set(2011, Calendar.MARCH, 27); PowerMockito.mockStatic(Calendar.class); Mockito.when(Calendar.getInstance()).thenReturn(endOfMarch); Refer to the link for the complete code.
Write a class called DateHelper with a method getCalendar that returns 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. Use that constructor in your test, to inject a mock of DateHelper, in which getCalendar has been stubbed to return some known date.
You can mockit using JMockit. Here you can see how you can do it: Mock Java Calendar - JMockit vs Mockito.
For those who follows MVP pattern mocking Calendar is a piece of cake:
In a Presenter create a method which returns calendar instance:
public Calendar getCurrentTime() { return Calendar.getInstance(); } In your view (Activity, Fragment etc) you access the calendar with help of presenter:
Calendar calendar = mPresenter.getCurrentTime(); // do whatever you want In your tests you do:
// create a dummy calendar Calendar mockCalendar = ... // You've already mocked your Presenter, haven't you? when(mMockPresenter.getCurrentTime()).thenReturn(mockCalendar); // here you are!