How to abstract away java.time.Clock for testing purposes in Spring
java, jsr310, junit, spring
Solution
Personally, I would simply add the clock in the constructor...
public MyServiceImpl(Clock clock) {
this.clock = clock;
}
...and perhaps add a nice default constructor...
public MyServiceImpl() {
this(Clock.systemDefaultZone());
}
This way you can get the default thing via spring and create a custom clock version manually, for example in your tests.
Of course, you could also forgo the default constructor and simply add a `Clock` bean in your productive configuration, for example like this...
@Bean
public Clock clock() {
return Clock.systemDefaultZone();
}
...which allows you to use a mocked `Clock` as a bean in your test configuration, automatically allowing Spring to `@Autowire` it via constructor injection.
Problem
I have a question with regards to the question Time dependent unit tests Let's say I build Spring application which contains service interface and its implementation If I want to change clock in test, I would have to "pollute" production code and interface with e.g. `setClock` method as follows: ``` public interface MyService { void heavyBusinessLogic(); void setClock(Clock clock); } @Service public class MyServiceImpl implements MyService { private Clock clock = Clock.systemDefaultZone(); @Override public void heavyBusinessLogic() { if (LocalDate.now(clock)...) { ... } } @Override public void setClock(Clock clock) { this.clock = clock; } } ``` In test, I can invoke, e.g.: ``` service.setClock(Clock.fixed(Instant.parse("2017-02-14T01:22:00Z"), ZoneOffset.UTC)); ``` How can I abstract away such cross-cutting concern in Spring? I want to stick with java.time.Clock (I don't want to use Joda)