January 17, 2012

Mocking with JodaTime's DateTime and Google Guava's Supplier



If you're a seasoned unit tester, you've learned to take note when you see any code working with time, concurrency, random, persistence and disc I/O.

The reason for this is that tests can be very brittle and sometimes down-right impossible to test properly. This post will show how to abstract out "time" by injecting a replacement for it in the consumer.  This post will be using Spring 3 as the Dependency Injection container, though Guice, other DI containers or constructor/setters on POJOs would work as well.  I will also ignore Locales since the focus is on the injection of the DateTime, not DateTime itself.

Existing code

You've been handed a piece of code to unit test (or you are creating one and this is your first stab at it).  Our first piece of code, only one class: (This class is a Spring 3.1 controller and the purpose is to return back the current time as a String)

@RequestMapping(value = "/time")
class TimeController {

    @RequestMapping(value = "/current", method = RequestMethod.GET)
    public String showCurrentTime() {
        // BAD!!! Can't test
        DateTime dateTime = new DateTime();
        return DateTimeFormat.forPattern("hh:mm").print(dateTime);

Take note that the class does a "new DateTime()" in the class.  Here is the corresponding test class:

What happens when we run the test?  How about assuming we have a very slow machine. You could (and most likely will) end up with your comparison DateTime to be different than the returned DateTime. This is a problem!

First thing to do is to remove the dependency, but how are we going to do this?  If we make the DateTime a field on the class, we will still have the same problem.  Introduce Google Guava's Supplier interface.

Google Guava Supplier

The Supplier interface only has one method, "get()" which will return an instance of whatever the supplier is setup for.  An example, the supplier will return a user's first name if they have logged in, and a default one if they have not:

public class FirstNameSupplier implements Supplier<String> {

    private String value;
    private static final String DEFAULT_NAME = "GUEST";

    public FirstNameSupplier() {
        // Just believe that this goes and gets a User from somewhere
        String firstName = UserUtilities.getUser().getFirstName();
        // more Guava
        if(isNullOrEmpty(firstName)) {
            value = DEFAULT_NAME;
        } else {
            value = firstName;

    public String get() {
        return value;

To your implementing method, you don't care what the first name is, only that you get one.

Refactoring out DateTime

Let's move on. For a much more real example of using a Supplier (and the point of this post) let's implement a DateTime supplier to give us back the current DateTime. While we're at it, let's also create an interface so that we can create mock implementations for testing:

public interface DateTimeSupplier extends Supplier<DateTime> {
    DateTime get();

and an implementation:

public class DateTimeUTCSupplier implements DateTimeSupplier {
    public DateTime get() {
        return new DateTime(DateTimeZone.UTC);

Now we can take the DateTimeUTCSupplier and inject that into our code that needs the current DateTime as the DateTimeSupplier interface:

@RequestMapping(value = "/time")
class TimeController {

    // Injected DateTimeSupplier
    DateTimeSupplier dateTime;

    @RequestMapping(value = "/current", method = RequestMethod.GET)
    public String showCurrentTime() {
        return DateTimeFormat.forPattern("hh:mm").print(dateTime.get());

In order to test this, we'll need to create a MockDateTimeSupplier and have a controller to pass in the specific instance we want to return:

public class MockDateTimeSupplier implements DateTimeSupplier {

    private final DateTime mockedDateTime;

    public MockDateTimeSupplier(DateTime mockedDateTime) {
        this.mockedDateTime = mockedDateTime;

    public DateTime get() {
        return mockedDateTime;

Notice that the object being saved is passed in via the constructor. This will not get you the current date/time back, but will return back the specific instance you want

and finally our test that exercises (slightly) the TimeController we implemented above:

public class TimeControllerTest {

    private final int HOUR_OF_DAY = 12;
    private final int MINUTE_OF_DAY = 30;

    public void testShowCurrentTime() throws Exception {
        TimeController controller = new TimeController();
        // Create the mock DateTimeSupplier with our known DateTime
        controller.dateTime = new MockDateTimeSupplier(new DateTime(2012, 1, 1, HOUR_OF_DAY, MINUTE_OF_DAY, 0, 0));

        // Call our method
        String dateTimeString = controller.showCurrentTime();

        // Using hamcrest for easier to read assertions and condition matchers
        assertThat(dateTimeString, is(String.format("%d:%d", HOUR_OF_DAY, MINUTE_OF_DAY)));



This post has shown how to use Google Guava's Supplier interface to abstract out a DateTime object so you can better design your implementations with unit testing in mind! Suppliers are a great way to solve the "just give me something", mind you it's a known type of something.

Good luck!


eneveu said...
This comment has been removed by the author.
eneveu said...

[trying again with proper HTML escaping]

Cool post.

Couldn't you avoid creating a DateTimeSupplier interface, and instead inject a Supplier directly?

Supplier<DateTime> dateTime;

In which case you wouldn't need the MockDateTimeSupplier class, and could instead do:

controller.dateTime = Suppliers.ofInstance(new DateTime(2012, 1, 1, HOUR_OF_DAY, MINUTE_OF_DAY, 0, 0));

Or would Spring's autowiring fail because it would have to inject a "generified bean" (Supplier), and the type info would be gone at runtime?

Anonymous said...

So you just described the factory pattern... no big deal

without having read the javadoc... is there more to the Supplier Interface than just being a predefined Factory interface?

Mike! said...

Hey Anonymous,

You're right, the Guava Supplier is a typed factory at it's core, but the main functionality comes from the ability to guarantee an result/object, pass and transform input and return Functions to be used within an algorithm.

This blog post is not specifically about Supplier interface, the blog post is about a possible solution to dealing with Dates and how to test them.

You've identified the pattern used here so probably know, almost all solutions involve at least one pattern from the original Gang of Four book. The point of this blog is not to show off brand new code for every solution, it is to share solutions to problems common to all developers and often times I find the simplest solution is to use existing open source software. I chose to use a Supplier instead of creating my own Factory pattern comes down to the "Don't repeat yourself" principal that every developer should know and love. Why re-write something that someone else has written and has been tested by tens of thousands of developers world wide?

I would suggest you read the JavaDocs on Supplier and while you're at it, many of the other amazing library additions to the Guava project (I use ImmutableList/ImmutableMap, Multimaps, Iterators, Strings, @VisibleForTesting, and many more)

Posting a comment with flame-tones in it does not help the community share information, nor does it foster an "ask anything, there are no stupid questions" attitude that I have tried to build. In the future, if you would like to flame a posting, please visit Facebook, Reddit or Twitter


Anonymous said...

Jodatime provides methods to "stop" the time in the class. http://joda-time.sourceforge.n.... Constructors use the methods in this class to initialize their fields. This can be useful for unit test without modifying the original code. Method to use setCurrentMillisFixed.

Anonymous said...

Sorry I forget name of class DateTimeUtils and link http://joda-time.sourceforge.net/apidocs/org/joda/time/DateTimeUtils.html

sorin cristea said...

Hi Mike,
Thanks for your post and explications. I don't understand exactly which is the advantage of using Supplier interface? From my point of view the only advantage is that we can use the injection directly, we are forced to implement the get() method, if there are other advantage please light me :). Thanks.

Mike! said...

I'll try to address these separately. First, setCurrentMillisFixed with the JodaTime constructors for dates is a solution, and while it is tread safe, it isn't parallelizable for tests. If you run tests concurrently and modify the system date in one test, you can't guarantee that the test will use the system date for that specific test case. This is why I recommend creating an abstraction for dates when creating calculations. Another possible strategy would be to pass around Intervals (I'm considering writing a post on that).

@sorin cristea, the Supplier interface is a very generic factory pattern (or some would like to call it a no-argument function). The advantages would be if you wanted to maybe look up a date from a database, if it isn't a suitable date, then return a default. The possibilities are pretty much endless on what you can use the Supplier for, I tend to think of it as (from the class level) "I don't really care where/how I will be getting this, but I can expect to get a workable object"


for IT the said...

Hi, Great.. Tutorial is just awesome..It is really helpful for a newbie like me.. I am a regular follower of your blog. Really very informative post you shared here. Kindly keep blogging. If anyone wants to become a Java developer learn from Java Training in Chennai. or learn thru Java Online Training India . Nowadays Java has tons of job opportunities on various vertical industry.

john kevin said...

I feel really happy to have seen your webpage and look forward to so many more entertaining times reading here. Thanks once more for all the details.

java training in bangalore
java training in bangalore

Nandhu said...

its very useful for us. more helpful. i really appreciate you to do and shared this kind of helpful blog with us.
Photoshop Training Institute in Chennai | Photoshop Training Institute in Velachery

Sarath K said...

Your blog is awesome..Your blog is explain each and every concept is good...
CorelDraw Training Institute in Chennai | Photoshop Training Institute in Chennai | CorelDraw Training Institute in Velachery

fawaz shaik said...

You are right, blogging teaches you a lot about yourself...
Best Photoshop Training Institute in Chennai | CorelDraw Training Institute in Chennai | No.1 Photoshop Training Institute in Velachery

mari A said...

Appreciation for really being thoughtful and also for deciding on certain marvelous guides most people really want to be aware of.

AWS Training in Chennai

krish said...

Needed to compose you a very little word to thank you yet again regarding the nice suggestions you’ve contributed here.
Good Graphics Designing Training Institute in Chennai | Best Multimedia Training Institute in Velachery

Ed Sheeran said...

wow really nice and useful article and explanation are very clear so easy to understand.. thanks a lot for sharing.
Photoshop Training Institute in Chennai | Best Multimedia Training Institute in Velachery

Ananya Krishnan said...

Good job in presenting the correct content with the clear explanation. The content looks real with valid information. Good Work

DevOps is currently a popular model currently organizations all over the world moving towards to it. Your post gave a clear idea about knowing the DevOps model and its importance.

Good to learn about DevOps at this time.

devops training in chennai | devops training in chennai with placement | devops training in chennai omr | devops training in velachery | devops training in chennai tambaram | devops institutes in chennai | devops certification in chennai | trending technologies list 2018

Unknown said...

Looking for the best online casino games? Come to us at BGAOC and win now perfect internet slots Luck will smile at you immediately.

venu bharath said...

Amazing Post. The content is very interesting. Waiting for your future updates.
Xamarin Training in Chennai
Xamarin Course in Chennai
Xamarin Training
Xamarin Course
Primavera Training in Chennai
Primavera Course in Chennai
IELTS coaching in Chennai
IELTS Training in Chennai

pavithra dass said...

Thanks for splitting your comprehension with us. It’s really useful to me & I hope it helps the people who in need of this vital information.
Java Training in Chennai
Java course in Chennai
Software Testing Training in Chennai
Web Designing Course in chennai
PHP Training in Chennai
Java Training in Tambaram
Java Training in OMR

jorick228 said...

Interested in details on online casinos? Come to us, here is all in full details. Top online casinos in the world Best casino only at BGAOC.

Belago said...

Я бы рекомендовал использовать профиль для светодиодных лент это нужно для того что бы лента дольше служила.

Maria said...

I started playing at simply real casino games after reading reviews from other players and I see that it’s not for nothing. Judging by the number of reviews on the Internet, it seems that only the lazy one did not play here)) Well, by the number of reviews and topics on the forums one can definitely say that this is one of the most popular players.

service care said...

I think this is a great site to post and I have read most of contents and I found it useful for my Career .Thanks for the useful information. Good work.Keep going.
motorola service center near me
motorola mobile service centre in chennai
moto g service center in chennai

Creators Seo Master said...

super your blog
andaman tour packages
andaman holiday packages
web development company in chennai
Math word problem solver
laptop service center in chennai
Austin Homes for Sale

anitha said...

Excellent Post. Extra-ordinary work to share with. Thanks for posting.
Node JS Training in Chennai
Node JS Course in Chennai
Node JS Advanced Training
Node JS Training Institute in chennai
Node JS Training in Velachery
Node JS Training in Tambaram
Node JS Training in OMR
Node JS Training in T Nagar

DedicatedHosting4u said...

Just seen your Article, it amazed me and surpised me with god thoughts that eveyone will benefit from it. It is really a very informative post for all those budding entreprenuers planning to take advantage of post for business expansions. You always share such a wonderful articlewhich helps us to gain knowledge .Thanks for sharing such a wonderful article, It will be deinitely helpful and fruitful article.

shivam said...

Flying Shift - Packers & Movers in Bhopal

tech updates said...

Nice blog

event management said...

Thanks for sharing this valuable information with us..
wedding photographers in chennai