rishabh agarwal
rishabh agarwal

Reputation: 99

How to mock clock.millis() in Java

I have a code where I calculate the difference between current clock time and time saved in my db If difference between the two is greater than certain value then I return result accordingly. For this case I am trying to write test but is facing problem to mock Clock.millis(). I have referred some answers but none worked for me can someone help me with that.This is my function

For my test I want to mock this clock.millis() function with a fixed value so that each time I run test it takes that value only.

Upvotes: 0

Views: 1311

Answers (2)

cassiomolin
cassiomolin

Reputation: 130957

A Clock is meant for providing access to the current instant, date and time using a time-zone. You don't really need to mock it. As your class needs to obtain the current instant, so it should receive an instance of the Clock in the constructor:

public class FooService {

    private final Clock clock;

    public FooService(Clock clock) {
        this.clock = clock;
    }

    public boolean isLocked() {
        long differenceInSecond = (clock.millis() - this.getLockedAt()) / 1000;
        return differenceInSecond < 7200;
    }

    private long getLockedAt() {
        ...
    }
}

Then, in your test, you can use a fixed() clock, which will always return the same instant:

@Test
public void isLocked_shouldReturnTrue_whenDifferenceInSecondIsSmallerThan7200() {

    // Create a fixed clock, which will always return the same instant
    Instant instant = Instant.parse("2020-01-01T00:00:00.00Z");
    Clock clock = Clock.fixed(instant, ZoneOffset.UTC);

    // Create a service instance with the fixed clock
    FooService fooService = new FooService(clock);

    // Invoke the service method and then assert the result
    boolean locked = fooService.isLocked();
    assertThat(locked).isTrue();
}

In a Spring Boot application, you could expose a Clock as a @Bean:

@Bean
public Clock clock() {
    return Clock.systemDefaultZone();
}

And then Spring will take care of injecting it into your service:

@Service
public class FooService {

    private final Clock clock;

    public FooService(Clock clock) {
        this.clock = clock;
    }

    ...
}

Upvotes: 5

Nicktar
Nicktar

Reputation: 5575

You need to wrap Clockinto your own class, exposing Clock.millis() as a delegate. In your test you can then mock your wrapper and return whatever you like.

Upvotes: 0

Related Questions