Current date and time mocking

140 views
Skip to first unread message

Dmitry Butakov

unread,
Dec 15, 2013, 10:14:04 AM12/15/13
to clean-code...@googlegroups.com
Hi,

Please help me to figure out how to mock functionality that's related to current time, date and so on. 

There should be a few classes that can check a possibility to get a discount according to their rules. 
For example there can be a class that gets a discount when current day of week is Sunday. Or when current time within predefined time frame.

I could create something like the following class hierarchy:

interface Matcher {
    int getDiscount();
}

class DayOfWeekMatcher implements Matcher {
    private DayOfWeek dayToBeMatched;
    private int discountValue;

    DayOfWeekMatcher(int discountValue, DayOfWeek dayToBeMatched) {
this.dayToBeMatched = dayToBeMatched;
this.discountValue = discountValue;
    }

    public int getDiscount() {
      // pseudo code
      return getCurrentDayOfWeek().equals(dayToBeMatched) ? discountValue : 0;
    }
 
    private DayOfWeek getCurrentDayOfWeek() {
// pseudo code
        return CURRENT_DOW;
    }
}

However there I see at least one problem, there is no way to set CURRENT_DOW outside the class. So the question is how to make getCurrentDayOfWeek be able to return "mocked" value? 

P.S. English isn't my native language, so if the problem's explanation isn't clear enough, please let me know.

Thanks,
Dmitriy

Per Lundholm

unread,
Dec 16, 2013, 2:10:48 AM12/16/13
to clean-code...@googlegroups.com

Hi
I think your English is just fine.
Don't know if this helps but I wrote about mocking the clock once.  There are some interesting comments to that post.
http://blog.crisp.se/2009/04/29/perlundholm/mock-the-clock

Cheers
Per

--
The only way to go fast is to go well.
---
You received this message because you are subscribed to the Google Groups "Clean Code Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clean-code-discu...@googlegroups.com.
To post to this group, send email to clean-code...@googlegroups.com.
Visit this group at http://groups.google.com/group/clean-code-discussion.

Juan Diego Hereñú

unread,
Dec 16, 2013, 8:23:46 AM12/16/13
to clean-code...@googlegroups.com
You just can make a class that manages Time where you can ask now() instead of doing a new Date().
You have a collaborator to manage time, maybe you can add different methods if you need them like yesterday(), tomorrow() or just getCurrentDayOfTheWeek. Then you can just Stub that collaborator to get the day that you wish in your test.

interface Matcher {
    int getDiscount();
}

class DayOfWeekMatcher implements Matcher {
    private DayOfWeek dayToBeMatched;
    private int discountValue;
    private DateProvider dateProvider

    DayOfWeekMatcher(int discountValue, DayOfWeek dayToBeMatched, DateProvider dateProvider) {
this.dayToBeMatched = dayToBeMatched;
this.discountValue = discountValue;
        this.dateProvider = dateProvider;
    }

    public int getDiscount() {
      // pseudo code
      return getCurrentDayOfWeek().equals(dayToBeMatched) ? discountValue : 0;
    }
 
    private DayOfWeek getCurrentDayOfWeek() {
        return dateProvider.getCurrentDayOfTheWeek();
    }
}

Last week I read a post on ticking, it doesn't apply for your problem but is a good reading for the future:


Hope it helps.
JD


2013/12/16 Per Lundholm <per.lu...@gmail.com>

Uncle Bob

unread,
Dec 18, 2013, 10:30:02 AM12/18/13
to clean-code...@googlegroups.com
The other folks who have replied have done a good job of describing the solution.  I'll just add this:

Time is just another input to the system.  You should control that input the way you control every other input.  Do not couple to external time services (like the OS).  Instead, as you would for _any_ IO service, create your own interface to that service and use that interface exclusively.  This will allow you to mock out the time for any test context.
Reply all
Reply to author
Forward
0 new messages