Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit testing a class with a Java 8 Clock

Java 8 introduced java.time.Clock which can be used as an argument to many other java.time objects, allowing you to inject a real or fake clock into them. For example, I know you can create a Clock.fixed() and then call Instant.now(clock) and it will return the fixed Instant you provided. This sounds perfect for unit testing!

However, I'm having trouble figuring out how best to use this. I have a class, similar to the following:

public class MyClass {     private Clock clock = Clock.systemUTC();      public void method1() {         Instant now = Instant.now(clock);         // Do something with 'now'     } } 

Now, I want to unit test this code. I need to be able to set clock to produce fixed times so that I can test method() at different times. Clearly, I could use reflection to set the clock member to specific values, but it would be nice if I didn't have to resort to reflection. I could create a public setClock() method, but that feels wrong. I don't want to add a Clock argument to the method because the real code shouldn't be concerned with passing in a clock.

What is the best approach for handling this? This is new code so I could reorganize the class.

Edit: To clarify, I need to be able to construct a single MyClass object but be able to have that one object see two different clock values (as if it were a regular system clock ticking along). As such, I cannot pass a fixed clock into the constructor.

like image 742
Mike Avatar asked Nov 21 '14 17:11

Mike


People also ask

How can I mock Java time LocalDate NOW ()?

You can refactor you code to make it test-friendly, for example, replace all invocations of LocalDate. now() with invocation of some method of custom mockable non-static class. Alternatively, you can use PowerMock's mockStatic. Show activity on this post.

Why do we write unit tests Java?

Developers write unit tests for their code to make sure that the code works correctly. This helps to detect and protect against bugs in the future. Sometimes developers write unit tests first, then write the code.

What is unit testing using JUnit?

JUnit is a Java unit testing framework that's one of the best test methods for regression testing. An open-source framework, it is used to write and run repeatable automated tests. As with anything else, the JUnit testing framework has evolved over time.


1 Answers

I don't want to add a Clock argument to the method because the real code shouldn't be concerned with passing in a clock.

No... but you might want to consider it as a constructor parameter. Basically you're saying that your class needs a clock with which to work... so that's a dependency. Treat it as you would any other dependency, and inject it either in a constructor or via a method. (I personally favour constructor injection, but YMMV.)

As soon as you stop thinking of it as something you can easily construct yourself, and start thinking of it as "just another dependency" then you can use familiar techniques. (I'm assuming you're comfortable with dependency injection in general, admittedly.)

like image 159
Jon Skeet Avatar answered Oct 09 '22 10:10

Jon Skeet