Showing posts with label supplier. Show all posts
Showing posts with label supplier. Show all posts

Tuesday, June 22, 2010

unit test and new Date()

A lot of code which use new Date() or System.currentTimeMillis() is quite impossible to unit test.

A too-current-in-every-day-life example method :

public class SomeClass {
    public String currentDateAsString() {
        return new SimpleDateFormat().format(new Date(), "yyyyMMdd");
    }
}

The corresponding unit test will not work for so long :

@Test
public void testCurrentDateAsString() {
    Assert.assertEquals("20100622", new SomeClass().currentDateAsString());
}

It will fail tomorrow ;-)

If you own the code, you should use a Date provider. Using library such as google collection (now guava), you can simply use a Supplier.

public class SomeClass {
    public SomeClass(String pattern, Supplier dateSupplier) {
        this.pattern = pattern;
        this.dateSupplier = dateSupplier;
    }

    public String currentDateAsString() {
        new SimpleDateFormat().format(this.dateSupplier.get(), this.pattern);
    }

    private final String pattern;
    private final Supplier dateSupplier;

}

Now the unit test will be much nicer  and more it follows the Law of Demeter :

@Test
public void testCurrentDateAsString() {
    Supplier dateSupplier = Suppliers.ofInstance(newDate(22,6,2010));
    Assert.assertEquals("20100622", new SomeClass("yyyyMMdd", dateSupplier).currentDateAsString());
}

*newDate may be a static date factory method you wrote, it is here for readability.

If the code come from scary legacy code, you should use jmockit or powermock (see Can I mock static methods).