Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Inject Clock.getInstance() in Spring Boot?

I want to unit test some code that calls System.currentTimeMillis(). As this answer points out, a good way to do this is to replace calls to System.currentTimeMillis() with Clock.getInstance().currentTimeMillis(). Then, you can perform dependency injection on Clock.getInstance(), for example to replace it with a mock in unit testing.

So, my question is a follow-up to that. How do you configure Spring Boot to inject Clock.getInstance() at runtime?

If possible, I'd prefer to do this with annotations instead of XML.

Also, if possible, I'd like to do this in such a way that I can simply use @Mock and @InjectMocks with MockitoJUnitRunner to inject a mock clock into a unit test.

like image 535
mkasberg Avatar asked Mar 07 '23 12:03

mkasberg


1 Answers

In your configuration class, you can do:

@Configuration
public class Config { 
    @Bean
    public Clock clock() { 
        return Clock.fixed(...);
    } 
} 

In your class you can just @Autowire it:

public class ClockUser {

private Clock clock;

    public ClockUser(Clock clock, ...) {
        this.clock = clock;
    }
}

(Notice I'm using constructor injection here, see the section entitled Constructor-based or setter-based DI of this article, Oliver Gierke's comment (i.e. head of Spring Data project), and google for more information.)

Then you can create your mock in another test @Configuration class or in your JUnit test:

@Bean
public Clock {
    Clock clock = Mockito.mock(Clock.class);
    .... ("when" rules)
    return clock;
} 
like image 156
Dovmo Avatar answered Mar 25 '23 13:03

Dovmo