In Grails, is there a good way to mock the current time using Joda time?

前端 未结 3 958
鱼传尺愫
鱼传尺愫 2020-12-30 09:50

I\'m writing some code that does date and time calculations against the current time. In Joda time, this is accessed through a (Java) constructor, as it is an immutable obje

相关标签:
3条回答
  • 2020-12-30 10:19

    you could just use good old-fashioned OO principles, e.g.

      interface TimeService {
        DateTime getCurrentTime()
    
        // other time-related methods
      }
    
      class JodaTimeService implements TimeService {
        DateTime getCurrentTime() {
          new DateTime()
        }  
      }
    
      class MockTimeService implements TimeService {
        DateTime getCurrentTime() {
          // return a fixed point in time
        }  
      }
    

    Your code should get a reference to an implementation of TimeService via dependency injection. In resources.groovy use the MockTimeService only when running the tests

    import grails.util.Environment
    
    beans = {    
        if (Environment.current == Environment.TEST) {
            timeService(MockTimeService)
    
        } else {
             timeService(JodaTimeService)
        }
    }
    
    0 讨论(0)
  • 2020-12-30 10:30

    I know this as already been accepted, but with Joda-time you can freeze and set it to be whatever you like. So you can freeze time, advance time, go backwards in time. Provided you're using Joda consistently, your objects will get "now" as whatever time you've set that to be.

    // Stop time (and set a particular point in time):
    DateTimeUtils.setCurrentMillisFixed(whenever);
    
    // Advance time by the offset:
    DateTimeUtils.setCurrentMillisOffset(offsetFromCurrent);
    
    // Restore time (you could do this in an @After method)
    DateTimeUtils.setCurrentMillisSystem();
    
    0 讨论(0)
  • 2020-12-30 10:35

    We ended up creating dateService with now() method. In unit tests we mock it with

    domainInstance.dateService = [ now: { currentTime } ] as DateService
    

    where currentTime is a unit test class field. This imposes everybody's dependency on dateService (our only nearly-global dependency), and for src classes one has to pass it by hand.

    Unit tests, OTOH, look pretty clear with it.

    0 讨论(0)
提交回复
热议问题