Can it be that no one can have a look at this? I even added a small example.
I've helped out with the Tomcat 7 embedded container a bit. I don't always keep up with the forums, so I just saw your post now.
I debugged into your test case. The VerifyError occurs when Tomcat is loading com.google.common.collect.ComputingConcurrentHashMap$ComputingSegment. Guava is a dependency of Weld. If I switch from Guava r09 to 12.0 I get the error on com.google.common.collect.ImmutableSortedMultiset$Builder, and the same if I then upgrade to MyFaces 2.1.8. If I switch to Weld 1.1.8.Final I get a "java.lang.IncompatibleClassChangeError: Implementing class" on com.google.common.base.Equivalences$Impl.
I believe this might be more of an issue with JSF/MyFaces and Weld/Guava, as opposed to anything specific to Tomcat, Arquillian, or the Arquillian Tomcat Embedded Container. See also:
I tried bringing everything up to date, and paring the project and deployable dependencies down to the basics required for your test case. Having done this it passes. I know that's not a solution per se, but perhaps you could build up from there to see exactly where it breaks down. I'll attach the updated project.
arq-2.zip 6.6 KB
Thanks for looking into this after so much time. Unfortunately that was my fourth and the last time i tried arquillian and gave up. Each time i spent at least a day or two on it. I won't be loosing more time on it any time soon. Anyway your answer will probably help some other poor soul that has lost hours trying to make arquillian work. I can say it is improving, and that is a good thing.
Obviously the problem is not with Arquillian per se, but rather with embedded containers in general. The exceptions you are struggling with are because of different versions of the same library available in the classpath without any classloading isolation. So your code relying on newer version of guava can't actually use it because there is already another version used by the embedded container. The same applies to Glassfish Embedded [cause weld is using guava, as Ian already pointed out]. I would strongly recommend switching to managed container. it will just save you from suffer.
Honestly I think the embedded containers are getting a bit of a bad rap lately. I find it very handy that my presentation tier can be checked out and integration tested with none of the setup required for a managed or remote container (not that such setup couldn't be automated). Also after about a year of writing numerous tests with the Tomcat embedded container I've had nothing but success with it. That said I don't try to test my entire stack with Arquillian.
I tried full stack functional testing years ago with Canoo, Cargo and DbUnit, and found it to be less than worthwhile. With so much complexity under test the test cases themselves were too involved to create, too brittle, too slow, and too coarse-grained for failures to tell me much of anything about what was actually broken. Despite whatever Arquillian can do to help address those first three issues, I'm not sure how much it can do about the last one. Full stack smoke testing has its place of course, but I've come to believe that full stack functional testing is just one of those things that sounds great in theory, but doesn't work out as such in practice.
I've now architected my app such that the only part which depends on the container is the JSP and Servlet spec related bits. These layers are what I use Arquillian to test--Servlet Filters; Servlets; JSPs with EL, JSTL and custom Tag File and Library usage; Struts and Tiles configuration--the Tomcat embedded container has helped me get solid coverage on all that essential code and configuration. I mock or stub out everything else behind that in my Arquillian tests, and instead test the implementations of those other tiers with Spring's Integration Testing facilities.
Of course we could rework embedded containers to isolate their classloaders. I touched on this a while back here: Should embedded containers use the launching test's classpath? I punted on the implementation because:
- I wasn't aware of anyone else asking for it.
- I wasn't running into any show-stopper issues myself by not having it.
- I'd need some infrastructure for specifying the classpath of the isolated classloaders. For Tomcat this would be the system and common classloaders. I'm not familiar enough with other containers to know how much they might differ here. All in all this piece seemed like it would be better suited for someone more familiar with Arquillian's core than I. At a high level I might imagine something like lists of Maven coordinates in the container configuration files, combined with ShrinkWrap's MavenDependencyResolver for on-demand fetching of those dependencies.
Just one remark - with JBoss AS managed there is almost zero setup as well (either mvn if you want to grab it and put unzipped in target dir or JBOSS_HOME to point Arquillian where the server sits).