Issues with await().until(). Failing even with correct value

1,964 views
Skip to first unread message

Maciej Biłas

unread,
Mar 28, 2011, 5:51:50 AM3/28/11
to await...@googlegroups.com
Hey,

I've been using awaitility in testing a project I work on.

I'm experiencing a very peculiar issue with it. Sometimes I set the timeout to 100 milliseconds (presumably it's too short) invoking await() like in the code below:

await().atMost(100, TimeUnit.MILLISECONDS).until(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return counter.get();
}
}, is(equalTo(Integer.valueOf(2))));

I get a strangely looking exception like this.

Well… actual == expected, yet an exception is thrown.

java.util.concurrent.TimeoutException: com.somecompany.AClass.shouldDoSomethingSensible Callable expected <2> but was <2> within 100 milliseconds.
at com.jayway.awaitility.core.ConditionAwaiter.await(ConditionAwaiter.java:87)
at com.jayway.awaitility.core.AbstractHamcrestCondition.await(AbstractHamcrestCondition.java:50)
at com.jayway.awaitility.core.ConditionFactory.until(ConditionFactory.java:438)
at com.jayway.awaitility.core.ConditionFactory.until(ConditionFactory.java:398)
at com.somecompany.AClass.shouldDoSomethingSensible(AClass:66)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
[…]

Is it me doing something wrong or have a just stumbled upon a bug in awaitility?

Cheers,
Maciej


Maciej Biłas
maciej...@gmail.com

Johan Haleby

unread,
Mar 28, 2011, 6:13:59 AM3/28/11
to await...@googlegroups.com
Hi, 

Hm it looks quite strange indeed. It could be that one value is a primtive and the other is a wrapper type. Try doing:

await().atMost(100, TimeUnit.MILLISECONDS).until(new Callable<Integer>() {
       @Override
               public Integer call() throws Exception {
                       return counter.get();
               }
       }, is(equalTo(2)));

and see if you get the same result. 

Another tip to make your test more readable is to extract the Callable into a new method or use the proxy-based approach:

await().atMost(100, MILLISECONDS).untilCall( to(counter).get(), is(2));

/Johan

Maciej Biłas

unread,
Mar 28, 2011, 6:43:54 AM3/28/11
to await...@googlegroups.com
No, it's not a boxed-unboxed issue. I've checked both variants.

I'm running Apple's Java 6 on OSX 10.6 on a 2010 MacBook Pro (Intel Core2 Duo). I think if you tweak the atMost time you should be able to reproduce it. Perhaps…

The counter in the Callable is an AtomicInteger so is should not be a data race issue.

Cheers,
Maciej

On Mar 28, 2011, at 12:13, Johan Haleby wrote:

Hi, 

Hm it looks quite strange indeed. It could be that one value is a primtive and the other is a wrapper type. Try doing:

await().atMost(100, TimeUnit.MILLISECONDS).until(new Callable<Integer>() {
       @Override
               public Integer call() throws Exception {
                       return counter.get();
               }
       }, is(equalTo(2)));


and see if you get the same result. 

Another tip to make your test more readable is to extract the Callable into a new method or use the proxy-based approach:

await().atMost(100, MILLISECONDS).untilCall( to(counter).get(), is(2));

/Johan

Maciej Biłas



Maciej Biłas

unread,
Mar 28, 2011, 7:38:24 AM3/28/11
to await...@googlegroups.com
On Mon, Mar 28, 2011 at 12:43 PM, Maciej Biłas <maciej...@gmail.com> wrote:
> and see if you get the same result.
> Another tip to make your test more readable is to extract the Callable into
> a new method or use the proxy-based approach:
> await().atMost(100, MILLISECONDS).untilCall( to(counter).get(), is(2));
> /Johan
Also if you were to run this yourself don't try to proxy approach with
an AtomicInteger, since all it's methods are final.

-- m.
--
Maciej Biłas

Johan Haleby

unread,
Mar 28, 2011, 7:53:53 AM3/28/11
to await...@googlegroups.com
That's true indeed (didn't know that the counter was an AtomicInteger) :)

Did you manage to solve your problem?

/Johan

Maciej Biłas

unread,
Mar 28, 2011, 8:09:13 AM3/28/11
to await...@googlegroups.com
On Mon, Mar 28, 2011 at 1:53 PM, Johan Haleby <johan....@gmail.com> wrote:
> That's true indeed (didn't know that the counter was an AtomicInteger) :)
> Did you manage to solve your problem?
> /Johan

Increasing the timeout solves it.

Nonetheless I find it strange to get an error message with values in
it being apparently correct.

-- m.
--
Maciej Biłas

maciej at inszy dot org

Johan Haleby

unread,
Mar 28, 2011, 8:14:58 AM3/28/11
to await...@googlegroups.com
You can also try decreasing the poll interval since the default poll interval is 100 ms. E.g.

with().pollInterval(20, MILLISECONDS).await().. 

Well if the problem is that your expected result is a wrapper type (Integer) and the actual result is a primitive type (int) then I suppose it could happen. How ever it's definitely not obvious by looking at the error message. But if really is the case then setting a longer time-out shouldn't affect the result.

/Johan

Jan Kronquist

unread,
Mar 29, 2011, 2:54:53 AM3/29/11
to await...@googlegroups.com, Johan Haleby
We should probably generate an Exception if the pollInterval is
greater than or equals to the max wait time!

Maybe something like this:

@Test(expected=IllegalStateException.class)
public void pollIntervalGreaterThanAMostShouldGenerateException()
throws Exception {
await().pollInterval(Duration.FIVE_SECONDS).atMost(ONE_SECOND);
}

/Jan

2011/3/28 Johan Haleby <johan....@gmail.com>:

Reply all
Reply to author
Forward
0 new messages