Can you show me how you would mock the current time of that method in Java?
It's one line of Ruby/Javascript code to do that.
Can you show me how you would mock the current time of that method in Java?
It's one line of Ruby/Javascript code to do that.
final Date testDate = someFixedDate;
User testUser = new User() {
@Override
Date say_current_time() {
return testDate;
}
};
If it is private and/or static, you can get around it without having to change the code, but if you own the code, you should just do that... Often the change will be as simple as replacing some method's raw usage of Date.now() with a local say_curent_time() method that uses it or some injected dependency just so you can mock Date.now() without hassle.But your point further down that in Java you have to think about your code structure more to accommodate tests is valid. I think it's easy to drink the kool-aid and start believing that many code structuring styles that enable easier testing in Java are actually very often just better styles regardless of language, but you're not going to really see the point if you do nothing but Ruby/JS where you can get away with not doing such things for longer. Mostly it has to do with dynamic languages offering looser and later and dynamic binding than static languages (which also frequently makes them easier to refactor even if you don't have automated tools). One big exception is if your language supports multiple dispatch, a lot of super ugly Java-isms go away and you shouldn't emulate them. The book Working Effectively with Legacy Code is a good reference for what works well in Java and C++ (and similar situations in other languages), it's mostly about techniques for breaking dependencies.
Mockito in Java has a nifty way of doing this with Mockito.mockStatic:
@Test
public void mockTime() throws InterruptedException {
LocalDateTime fake = LocalDateTime.of(2021, 7, 2, 19, 0, 0);
try (MockedStatic<LocalDateTime> call = Mockito.mockStatic(LocalDateTime.class)) {
call.when(LocalDateTime::now).thenReturn(fake);
assertThat(LocalDateTime.now()).isEqualTo(fake);
Thread.sleep(2_000);
assertThat(LocalDateTime.now()).isEqualTo(fake);
}
LocalDateTime now = LocalDateTime.now();
assertThat(now).isAfter(fake);
assertThat(now).isNotEqualTo(fake);
}
Or you can pass a Clock instance and use .now(clock). That Clock then can be either a system clock or a fixed value.Yes, that was my point. I see it's possible in Java though, hurts my eyes a bit but possible :)
Instant testNow = ...
User u = new User(Clock.fixed(testNow, ZoneOffset.UTC));
u.sayCurrentTime();
although it would be better design to have sayCurrentTime take a date parameter instead of depending on an external dependency. User mock = mock(User.java)
when(mock.say_current_time()).thenReturn(someDate)And again if this is possible I will admit ignorance and tip my hat at the Java guys.
https://javadoc.io/static/org.mockito/mockito-core/3.11.2/or...
User mock = mock(User.java)
Should have been
User mock = mock(User.class)