> I tried writing some learning tests for Quartz a couple months back.
> For what it's worth, I ran into the same timing issues.
>
> Before reaching for sleep(), I tried to refactor Quartz innards so that
> the internal clock could be programmatically advanced. Unfortunately,
> a direct call to System.currentTimeMillis() was duplicated in many
> places and even after consolidating all those calls through an
> interface I was unable to mock the clock.
I have done that as well. My Clock interface encapsulates
System.currentTimeMillis(), new Date(), Calendar.getInstance(), and
Thread.sleep(). There may be other standard API mechanisms that operate
on the current system time, but those were the only ones in use in the
code I was refactoring.
Most of those were no problem, but pause (the method that encapsulates
Thread.sleep()) was very difficult to fake. The problem is that when
thread A calls pause, all other threads have to be given a chance to
call pause before thread A is woken up. This is tricky because thread
scheduling in Java is inherently unpredictable, and in Java 1.4 and
earlier there is no way to determine whether any given thread is
runnable or not. As a result the FakeClock is as reliable as most
mechanisms for testing multi-threaded code: not perfectly.
But the tests are an order of magnitude faster than they were when they
just used Thread.sleep(), and they are as reliable as they were before,
so that's good enough for me.
(Incidentally, in Java 1.5, you can call getState() on a Thread and
thereby determine whether it is currently runnable, blocked, waiting, in
a timed wait, etc. But I'm stuck with Java 1.4 at the moment.)
The code for my Clock interface, and the SystemClock and FakeClock
implementations, isn't currently online anywhere, but if anyone is
interested let me know and I'll send it over.
I don't think there are any really good solutions to testing
multithreaded code in Java at the moment. The only general approach
I've thought of that SHOULD work properly is to use JDI to launch a
separate JVM, and execute the test in that other JVM. (JDI can be used
to set breakpoints and method entry watchers, and thereby control
scheduling absolutely in the test VM.) But that's a lot of work, and I
haven't yet been sufficiently motivated to build such a facility.
Cheers,
bn
--
Brett Neumeier <[EMAIL PROTECTED]>
| Yahoo! Groups Sponsor | |
|
|
Yahoo! Groups Links
- To visit your group on the web, go to:
http://groups.yahoo.com/group/junit/
- To unsubscribe from this group, send an email to:
[EMAIL PROTECTED]
- Your use of Yahoo! Groups is subject to the Yahoo! Terms of Service.
