JSFUnit and Tomcat 7
atsteffen Jan 12, 2012 11:07 PMHi All,
I'm thrilled to get some CDI unit tests running for my Tomcat 7 web app. But i've had mixed luck so far. I'm wondering how well others have fared using JSFUnit 2.0/Arquillian with Tomcat 7. I'm somewhat invested in using tomcat 7 for my application, but I'm not sure I can live without unit tests for my CDI beans and such. Do you all think this the best route (jsfunit) right now for adding integration testing to my project? I realize things are still in development. In any case I thought I would put down what I've done so far, and hopefully get some help refining it to a working example.
Here's a test project layout:
HelloJSFTest.java:
@RunWith(Arquillian.class) public class HelloJSFTest { @Deployment public static WebArchive createDeployment() { WebArchive war = ShrinkWrap.create(WebArchive.class, "test.war") .setWebXML(new File("src/main/webapp/WEB-INF/web.xml")) .addClass(MyBean.class) .addAsWebResource(new File("src/main/webapp", "index.xhtml")) .addAsManifestResource("context.xml", "context.xml") .addAsWebInfResource(new File("src/main/webapp/WEB-INF/faces-config.xml"), "faces-config.xml") .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml"); //System.out.println(war.toString(true)); // for debugging return war; } @Inject MyBean userbean; @Test public void testUserBeanInjection() { Assert.assertNotNull(userbean); } @Test public void beanHasAccessToClassDependencies() { Assert.assertFalse(userbean.isLoggedIn()); } @Test @InitialPage("/index.faces") public void testInitialPage(JSFServerSession server, JSFClientSession client) throws IOException { // Test navigation to initial viewID Assert.assertEquals("/index.xhtml", server.getCurrentViewID()); // Set the param and submit client.setValue("name", "Stan"); client.click("submit_button"); // Assert that the greeting component is in the component tree and rendered UIComponent greeting = server.findComponent("greeting"); Assert.assertTrue(greeting.isRendered()); // Test a managed bean using EL. We cheat and use the request object. Assert.assertEquals("Stan", server.getManagedBeanValue("#{request.getParameter('form1:name')}")); } }
arquillian.xml:
<?xml version="1.0" encoding="UTF-8"?> <arquillian xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jboss.org/schema/arquillian http://jboss.org/schema/arquillian/arquillian-1.0.xsd"> <engine> <property name="deploymentExportPath">target/</property> </engine> <container qualifier="tomcat" default="true"> <configuration> <property name="bindHttpPort">8888</property> <property name="unpackArchive">true</property> <property name="user">tomcat</property> <property name="pass">tomcat</property> </configuration> </container> <defaultProtocol type="Servlet 3.0" /> </arquillian>
context.xml:
<?xml version="1.0" encoding="UTF-8"?> <Context> <Resource name="BeanManager" auth="Container" type="javax.enterprise.inject.spi.BeanManager" factory="org.jboss.weld.resources.ManagerObjectFactory"/> </Context>
web.xml:
<?xml version="1.0"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0"> <listener> <listener-class>org.jboss.weld.environment.servlet.Listener</listener-class> </listener> <servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>*.faces</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list> <filter> <filter-name>JSFUnitCleanupTestTreadFilter</filter-name> <filter-class>org.jboss.jsfunit.arquillian.container.JSFUnitCleanupTestTreadFilter</filter-class> </filter> <filter> <filter-name>JSFUnitFilter</filter-name> <filter-class>org.jboss.jsfunit.framework.JSFUnitFilter</filter-class> </filter> <filter-mapping> <filter-name>JSFUnitCleanupTestTreadFilter</filter-name> <url-pattern>/ArquillianServletRunner</url-pattern> </filter-mapping> <filter-mapping> <filter-name>JSFUnitFilter</filter-name> <url-pattern>/ArquillianServletRunner</url-pattern> </filter-mapping> </web-app>
pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.jboss.jsfunit</groupId> <artifactId>gettingstarted</artifactId> <version>2.0.0.Beta2</version> <packaging>war</packaging> <name>Minimal example for the Getting Started Guide</name> <repositories> <repository> <id>jboss-public-repository-group</id> <name>JBoss Public Maven Repository Group</name> <url>http://repository.jboss.org/nexus/content/groups/public</url> <layout>default</layout> <releases> <enabled>true</enabled> <updatePolicy>never</updatePolicy> </releases> <snapshots> <enabled>false</enabled> <updatePolicy>never</updatePolicy> </snapshots> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>jboss-public-repository-group</id> <name>JBoss Public Maven Repository Group</name> <url>http://repository.jboss.org/nexus/content/groups/public</url> <layout>default</layout> <releases> <enabled>true</enabled> <updatePolicy>never</updatePolicy> </releases> <snapshots> <enabled>true</enabled> <updatePolicy>never</updatePolicy> </snapshots> </pluginRepository> </pluginRepositories> <properties> <version.jsfunit>2.0.0.Beta2</version.jsfunit> <version.arquillian>1.0.0.CR4</version.arquillian> <version.shrinkwrap>1.0.0-beta-5</version.shrinkwrap> <version.shrinkwrap.descriptors>1.1.0-alpha-2</version.shrinkwrap.descriptors> <version.org.apache.tomcat>7.0.22</version.org.apache.tomcat> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.8.2</version> <scope>test</scope> </dependency> <dependency> <groupId>org.jboss.arquillian.junit</groupId> <artifactId>arquillian-junit-container</artifactId> <version>${version.arquillian}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.jboss.arquillian.protocol</groupId> <artifactId>arquillian-protocol-servlet</artifactId> <version>${version.arquillian}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.jboss.arquillian.container</groupId> <artifactId>arquillian-container-spi</artifactId> <version>${version.arquillian}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.jboss.jsfunit</groupId> <artifactId>jsfunit-arquillian</artifactId> <version>${version.jsfunit}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.jboss.jsfunit</groupId> <artifactId>jboss-jsfunit-core</artifactId> <version>${version.jsfunit}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.jboss.shrinkwrap.descriptors</groupId> <artifactId>shrinkwrap-descriptors-impl</artifactId> <version>${version.shrinkwrap.descriptors}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.jboss.shrinkwrap.resolver</groupId> <artifactId>shrinkwrap-resolver-api-maven</artifactId> <version>${version.shrinkwrap}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.jboss.shrinkwrap.resolver</groupId> <artifactId>shrinkwrap-resolver-impl-maven</artifactId> <version>${version.shrinkwrap}</version> <scope>test</scope> </dependency> <dependency> <groupId>javax.faces</groupId> <artifactId>jsf-api</artifactId> <version>2.0</version> </dependency> <dependency> <groupId>javax.faces</groupId> <artifactId>jsf-impl</artifactId> <version>2.0.2-FCS</version> </dependency> </dependencies> <profiles> <profile> <id>tomcat-embedded</id> <dependencies> <dependency> <groupId>org.jboss.arquillian.container</groupId> <artifactId>arquillian-tomcat-embedded-7</artifactId> <version>1.0.0.CR2</version> <scope>test</scope> </dependency> <dependency> <groupId>org.apache.tomcat</groupId> <artifactId>tomcat-catalina</artifactId> <version>${version.org.apache.tomcat}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.apache.tomcat</groupId> <artifactId>tomcat-coyote</artifactId> <version>${version.org.apache.tomcat}</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.tomcat</groupId> <artifactId>tomcat-jasper</artifactId> <version>${version.org.apache.tomcat}</version> <scope>provided</scope> </dependency> <!-- Weld servlet, EL and JSP required for testing CDI injections --> <dependency> <groupId>org.jboss.weld.servlet</groupId> <artifactId>weld-servlet</artifactId> <version>1.0.1-Final</version> <scope>test</scope> </dependency> </dependencies> </profile> </profiles> </project>
I followed the advice of @hettothecool in this discussion: https://community.jboss.org/wiki/JSFUnit20AndTomcat6. Using this pom.xml, web.xml and arquillian.xml plus some modifications I get things mostly running. Oddly enough my tests only run successfully in eclipse. When I try to run my test using "mvn -Ptomcat-embedded test", I get errors:
java.lang.IllegalStateException: Application was not properly initialized at startup, could not find Factory: javax.faces.context.FacesContextFactory at javax.faces.FactoryFinder$FactoryManager.getFactory(FactoryFinder.java:804) at javax.faces.FactoryFinder.getFactory(FactoryFinder.java:306) at javax.faces.webapp.FacesServlet.init(FacesServlet.java:166) at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1228) at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1147) ....
I've attached the sunfire report for this error which gives:
java.lang.RuntimeException: Could not inject method parameters at org.jboss.jsfunit.arquillian.container.JSFUnitTestEnricher.resolve(JSFUnitTestEnricher.java:89) at org.jboss.arquillian.container.test.impl.execution.LocalTestExecuter.enrichArguments(LocalTestExecuter.java:94) .....
I find it really odd that importing a project to eclipse leads to a successful run, while using the terminal does not. Any help with this specific issue or pointers to add to my test project would be appreciated.
Adam