How can I mock JodaTime actual date?

末鹿安然 提交于 2019-12-22 01:33:28

问题


I want to test this method:

 public FirmOrder findActiveByModelColor(ModelColor modelColor) {
   Query query = em.createQuery("FROM FirmOrder fo WHERE fo.modelColor = :modelColor AND fo.year = :year AND fo.month = :month");
   query.setParameter("modelColor", modelColor);
   query.setParameter("year", new DateTime().year().get());
   query.setParameter("month", new DateTime().monthOfYear().get());
   return (FirmOrder) query.getSingleResult();
 }

but I need DateTime().year().get() and DateTime().dayOfMonth().get() to always return the same date

tks


回答1:


If you can't add a factory object as suggested by skaffman, you can use DateTimeUtils.setCurrentMillisFixed().




回答2:


Then you need to define a Clock interface, and inject it into your class

public interface Clock {
    DateTime getCurrentDateTime();
}

then:

Clock clock;

public FirmOrder findActiveByModelColor(ModelColor modelColor) {
   Query query = em.createQuery("FROM FirmOrder fo WHERE fo.modelColor = :modelColor AND fo.year = :year AND fo.month = :month");
   query.setParameter("modelColor", modelColor);
   query.setParameter("year", clock.getCurrentDateTime().year().get());
   query.setParameter("month", clock.getCurrentDateTime().dayOfMonth().get());
   return (FirmOrder) query.getSingleResult();
 }

Your test can then inject an implementation of Clock (e.g. using a mocking framework) that always returns a fixed time.

I use the Clock interface a lot in my own stuff, and I remain surprised that it's not part of one of the common libraries out there. I have two implementations I use a lot, WallClock and StoppedClock (which is useful for tests that use a fixed time).




回答3:


Looks like the only option is to use the answer feature to post this comment:

The following portion of your code can lead to hard-to-detect errors:

query.setParameter("year", new DateTime().year().get());
query.setParameter("month", new DateTime().monthOfYear().get());

Let's pretend tha today is the last day of the year 2011 and this part of code is called 1 nano second prior to the new year and that the first statement takes more than 1 nano second to complete. This means that year will be set to 2011 but month to 1 but it had to best either to 2011/12 or 2012/1.

Though that statistically it is very unlikely to happen, but logically it can happen :)

You should create one DateTime instance and use that to populate both of year and month.




回答4:


It's easy, if using the JMockit Expectations mocking API:

@Test
public void findActiveByModelColor()
{
    new NonStrictExpectations()
    {
        @Cascading DateTime dt;

        {
            dt.year().get(); result = 2010;
            dt.monthOfYear().get(); result = 12;
        }
    };

    FirmOrder fo = testedObject.findActiveByModelColor(modelColor);

    // asserts...
}


来源:https://stackoverflow.com/questions/4454106/how-can-i-mock-jodatime-actual-date

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!