0

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.

rishabh agarwal
  • 99
  • 1
  • 13
  • 2
    Please post code as code and not as screenshot. – Nicktar Feb 18 '20 at 11:36
  • Take a look at these questions: [Mocking static methods with Mockito](https://stackoverflow.com/questions/21105403/mocking-static-methods-with-mockito) and [Mocking time in Java 8's java.time API](https://stackoverflow.com/questions/24491260/mocking-time-in-java-8s-java-time-api) – default locale Feb 18 '20 at 11:44
  • I found many solutions with PowerMockRunner but I have to use PandoraBootRunner can you help me in that – rishabh agarwal Feb 18 '20 at 11:46
  • 2
    If you correctly wrote your code to use *injection*, so the [`Clock`](https://docs.oracle.com/javase/8/docs/api/java/time/Clock.html) is injected, then you can unit test the code by passing in a different `Clock`, e.g. a [`fixed()`](https://docs.oracle.com/javase/8/docs/api/java/time/Clock.html#fixed-java.time.Instant-java.time.ZoneId-) clock, and you wouldn't need to mock anything. – Andreas Feb 18 '20 at 12:00

2 Answers2

5

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;
    }

    ...
}
cassiomolin
  • 124,154
  • 35
  • 280
  • 359
0

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.

Nicktar
  • 5,548
  • 1
  • 28
  • 43