Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Say you have a property startTime. Then you have a method doSomething:

doSomething() {
   //...stuff
   startTime = System.currentTimeMillis();
   //... more stuff
}

How do you test that startTime was assigned correctly? You can't test against an absolute timestamp - it'll likely change between assignment and test. Maybe use a range?

share|improve this question
1  
Why would you want to test whether the assignment was done correctly? Apart from the type of startTime, there's nothing there that could go wrong. Or do you mean whether currentTimeMillis() returns a reasonable value? In that case I would just print it and look. –  Deckard Apr 19 '11 at 14:46
1  
Also this is for an automatic unit test, not visual inspection. –  Michael K Apr 19 '11 at 14:49
1  
It might not be assigned if the assignment statment didn't exist. If the statement got deleted in a refactoring, say... –  Michael K Apr 19 '11 at 14:53
1  
If a statement got deleted in a refactoring, lots of things would break. Test stuff that matters in the end. Interfaces. API's. The final results. –  S.Lott Apr 19 '11 at 14:56
1  
@S.Lott The reason this question came up is exactly that :) I refactored, this wasn't in the tests, and the whole thing blew up. I want a regression test to prevent it from happening again. –  Michael K Apr 19 '11 at 15:00

4 Answers 4

up vote 11 down vote accepted

One simple way is to pass in the time from outside the method:

doSomething(long currentTime) {
   //...stuff
   startTime = currentTime;
   //... more stuff
}

Your production code that calls the method can pass in the real value for System.currentTimeMillis(), whereas your unit test(s) can pass in a specific known value.

Of course, this isn't quite the same as your original. Another possibility that is a little more complex but should mimic the behaviour of your of your original more closely:

doSomething(ITimeGetter timeGetter) {
   //...stuff
   startTime = timeGetter.GetCurrentTime;
   //... more stuff
}

Define the interface:

interface ITimeGetter
{
   long GetCurrentTime();
}

Two implementations, one for the production code:

class RealTimeGetter implements ITimeGetter
{
  long GetCurrentTime()
  {
      return System.currentTimeMillis();
  }
}

One for the unit tests:

class TimeGetterForTests implements ITimeGetter
{
  long GetCurrentTime()
  {
     // return a known value.
  }
}

Instantiate an ITimeGetter appropriate to your scenario and pass it in to the method you want to test.

share|improve this answer
    
+1 I can think of several use-cases that this method would be perfect for. –  Michael K Apr 19 '11 at 14:50
3  
And this is why Dependency Injection and testing go hand in hand :) –  Martijn Verburg Apr 19 '11 at 15:10
1  
Now, why is an interface that returns the current time called ITime*Setter*? –  Cwan Apr 19 '11 at 15:52
    
Definitely do this by an interface, but use a mocking framework to create your mock object or you will start to get code bloat in your tests and they will become more coupled to your production code than you want and is necessary. –  user23157 Apr 19 '11 at 21:32
    
@Cwan: Stupdity. I've renamed the interface in my answer. Thanks for pointing that out. –  Kramii Apr 20 '11 at 5:50

Martin Fowler just wrote an interesting blog post about tests that may fail. He also writes about how you should handle time i.e. by wrapping the System call in a separate object.

Generally speaking, when you communicate with outside resources, for testing and encapsulation, it always helps to wrap them into objects.

share|improve this answer
    
...and he has a section about time, too! Does seem like a lot of boilerplate to wrap system objects all the time though. I haven't seen a library for that yet. You'd have to write yhour own. –  Michael K Apr 19 '11 at 15:16

While I personally favor Kramii's answer, there are also frameworks like Moles that allow detouring of static system calls.

share|improve this answer

You need to abstract out the timestamp mechanism so you can mock it.

This will allow you to generate exactly those results from currentTimeMillis that you need for testing, so you can be certain that values are correct.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.