问题
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