Brandon E Taylor
Brandon E Taylor

Reputation: 25349

Mocking System.nanoTime()

One can use Clock to mock calls like System.currentTimeMillis() using Clock.millis() and injecting a mock implementation of Clock.

Is there a similar way to easily mock System.nanoTime()?

Upvotes: 5

Views: 1097

Answers (4)

Steven Chou
Steven Chou

Reputation: 2215

You can use a interface for dependency injection during unit tests:

public class YourClass {
    private static TimeSupplier timeSupplier = System::nanoTime;

    @VisibleForTesting
    public static void setTimeSupplier(TimeSupplier timeSupplier) {
        YourClass.timeSupplier = timeSupplier;
    }

    @FunctionalInterface
    interface TimeSupplier {
        long nanoTime();
    }
    
    // Just use timeSupplier.nanoTime() instead of the static nanoTime calls
}

Then you can simply stub the timeout with a constant (Mockito for example):

YourClass.TimeSupplier timeSupplier = mock(YourClass.TimeSupplier.class);
when(timeSupplier.nanoTime()).thenReturn(20221116L);
YourClass.setTimeSupplier(timeSupplier);

Upvotes: 3

Petr Janeček
Petr Janeček

Reputation: 38434

You can use Google Guava's Ticker class that does exactly that.

Or, if you're simply trying to measure time properly, you can use Stopwatch for extra functionality and nicer API, its constructor takes a Ticker instance.

There's even a FakeTicker in guava-testlib if you find any of the other utilities in there useful. Otherwise writing a fake Ticker is obviously very easy.

Upvotes: 1

Olivier Grégoire
Olivier Grégoire

Reputation: 35437

Use your own encapsulation

interface NanoTimer {
  long nanoTime();
  static NanoTimer system() {
    return System::nanoTime;
  }
}

This way you can write your own mock very easily.

Alternatively, I can't see any use case besides a stopwatch, so I guess that you'd probably want to have a look at Guava's Stopwatch

Upvotes: 3

Honza Zidek
Honza Zidek

Reputation: 20066

Use Clock.instant(). According to documentation:

the class stores a long representing epoch-seconds and an int representing nanosecond-of-second

You can access the nano-part using Instant.getNano().

It's not equivalent, but it's analogous and it provides you with the same functionality. You even do not need to read the nano value, Instant represents the nano time. And you have arithmetical functions defined on the Instant class, such as minus(Instant), minusNanos(long) etc.

Upvotes: -2

Related Questions