liangzai-cool / hamcrest

Automatically exported from code.google.com/p/hamcrest
0 stars 0 forks source link

javac compilation problem #82

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
I started using hamcrest 1.2 a few days ago and i am really happy about it.
Today i run compilation of test classes in maven and to my surprise these
do not compile!.
For example trying to compile the following code:
Assert.assertThat(3, either(comparesEqualTo(4)).or(comparesEqualTo(3)));

i got compilation error:
or(org.hamcrest.Matcher<? super java.lang.Object>) in
org.hamcrest.core.CombinableMatcher<java.lang.Object> cannot be applied to
(org.hamcrest.Matcher<ca
pture of ? super java.lang.Integer>)
                Assert.assertThat(3,
either(comparesEqualTo(4)).or(comparesEqualTo(3)));

I found a post on John Ferguson blog
(http://weblogs.java.net/blog/johnsmart/archive/2008/04/on_the_subtle_u.html)
and on its basis I was able to create a workaround:
CombinableMatcher<Integer> either = either(comparesEqualTo(4));
Assert.assertThat(4, either.or(comparesEqualTo(3)));

Unfortunately this make my tests clumsy and unreadable. 

1. I am wondering why this code compile in Eclipse and not outside eclipse
(by execution javac, ant or maven) ?
2. Can anything can be done about it ?

Original issue reported on code.google.com by jmilkiew...@gmail.com on 27 May 2009 at 4:39

GoogleCodeExporter commented 9 years ago
After playing more with my code the following also compiles outside IDE
Assert.assertThat(4,Matchers<Integer>either(comparesEqualTo(4)).or(comparesEqual
To(3)));

Original comment by jmilkiew...@gmail.com on 27 May 2009 at 5:54

GoogleCodeExporter commented 9 years ago
Unfortunately, the design of Java generics seems to be flaky, so different 
compilers sometimes interpret 
differently. It also means that sometimes the compiler needs help with type 
inference by locking down one of 
the genericised arguments.

Have you tried this with equalTo(4), rather than going through a Comparable?

Rather than using intermediate objects, I sometimes use little helper methods 
to construct a clause and force 
the type. That also means I can give it a helpful name.

Original comment by smgfree...@gmail.com on 28 May 2009 at 9:18

GoogleCodeExporter commented 9 years ago
Hi

Thanks for an answer. Unfortunately this also does not compile:
Assert.assertThat(3, either(equalTo(4)).or(equalTo(3)));

It is a pity generics in Java works like that...

Original comment by jmilkiew...@gmail.com on 28 May 2009 at 9:41

GoogleCodeExporter commented 9 years ago
Btw the problems stands of course for arrays too, here's my simple workaround

assertThat(arrayOfTypeError, Matchers.<Error[]> 
both(hasItemInArray(expectedError1)).and(hasItemInArray(expectedError2)));

instead of :
assertThat(arrayOfTypeError, 
both(hasItemInArray(expectedError1)).and(hasItemInArray(expectedError2)));

This doesn't clutter the code too much, but for more complex matchers, I guess 
using 
a reference could be usefull.

Original comment by brice.du...@gmail.com on 25 Sep 2009 at 12:19

GoogleCodeExporter commented 9 years ago
Hi

A i stated in my second message i also try to help the compiler by specyfing 
explicitly runtime parameter type for parametrized types.
Beside, IDE (eclipse) is not as restrictive as maven/ant compilation and some 
of 
these subtle generics bugs are only raised by my CI system.

Original comment by jmilkiew...@gmail.com on 25 Sep 2009 at 2:31

GoogleCodeExporter commented 9 years ago
tagging

Original comment by t.denley on 12 May 2012 at 10:55

GoogleCodeExporter commented 9 years ago
It is not just Eclipse VS JDK, the same issue can happen with different JDK 
versions: 
it compiled locally with maven using JDK 1.6.0u45, but not on CI with maven 
using JDK 1.6.0u20.

Original comment by papp.robert.s on 30 May 2014 at 4:46