Java micro-library for writing & testing concurrent code
Timeout in JMock Synchroniser
JMock’s Synchroniser serialises access to the mock object’s “context”, it means all invocations of mocked methods call will be synchronized on the same monitor, effectively forcing them to run in sequence without thread safety concerns. As it uses synchronized though, you can (with some effort) get into trouble with tests that never finish.
If you’re seeing this kind of thing, apart from using the @Test(timeout=1000) annotation, you might consider an alternative ThreadingPolicy implementation using Locks that can timeout and maintain liveliness.
publicclassTimingOutSynchroniserimplementsThreadingPolicy{privatefinalLocklock=newReentrantLock();privatefinalConditionawaitingStatePredicate=lock.newCondition();privatefinalDurationlockTimeout;privateErrorfirstError=null;publicTimingOutSynchroniser(){this(millis(250));}publicTimingOutSynchroniser(Durationtimeout){this.lockTimeout=timeout;}publicvoidwaitUntil(StatePredicatepredicate)throwsInterruptedException{waitUntil(predicate,newInfiniteTimeout());}/** * Waits up to a timeout for a StatePredicate to become active. Fails the * test if the timeout expires. */publicvoidwaitUntil(StatePredicatepredicate,longtimeoutMs)throwsInterruptedException{waitUntil(predicate,newFixedTimeout(timeoutMs));}privatevoidwaitUntil(StatePredicatepredicate,TimeouttestTimeout)throwsInterruptedException{try{lock.tryLock(lockTimeout.inMillis(),MILLISECONDS);while(!predicate.isActive()){try{awaitingStatePredicate.await(testTimeout.timeRemaining(),MILLISECONDS);}catch(TimeoutExceptione){if(firstError!=null)throwfirstError;Assert.fail("timed out waiting for "+asString(predicate));}}}finally{if(lock.tryLock())lock.unlock();}}publicInvokablesynchroniseAccessTo(finalInvokablemockObject){returnnewInvokable(){publicObjectinvoke(Invocationinvocation)throwsThrowable{returnsynchroniseInvocation(mockObject,invocation);}};}privateObjectsynchroniseInvocation(InvokablemockObject,Invocationinvocation)throwsThrowable{try{lock.tryLock(lockTimeout.inMillis(),MILLISECONDS);try{returnmockObject.invoke(invocation);}catch(Errore){if(firstError==null)firstError=e;throwe;}finally{awaitingStatePredicate.signalAll();}}finally{if(lock.tryLock())lock.unlock();}}}