It's better to always "fail fast" during a build, than to possibly fail during runtime.
JSFUnit provides a set of unit tests for static analysis of JSF applications:
org.jboss.jsfunit.analysis.AbstractFacesConfigTestCase and org.jboss.jsfunit.analysis.AbstractTldTestCase . These classes have been checked into the Subversion repository, but they are not released yet.
Extending org.jboss.jsfunit.analysis.AbstractViewTestCase
%%(color:green)
public class ViewTestCase extends org.jboss.jsfunit.analysis.AbstractViewTestCase {
private static Set absoluteViewPaths = new HashSet<String>() {{
add("C:/work/project/src/home.xhtml");
}};
private static Set recursiveViewPaths = new HashSet<String>() {{
add("C:/work/project/src/views");
}};
public MyViewTestCase() {
super(absoluteViewPaths, recursiveViewPaths,
"C:/work/project/src/faces-config.xml");
}
}
%%
Do any of your facelets templates or well formed JSPs reference nonexistent managed beans?
<h:commandButton value="Home" action="#{missingBean.myAction}" />
%%(color:red)junit.framework.AssertionFailedError: C:/work/workspace/jsf-unit/src/views/home.xhtml has an EL expression '#{missingBean.myAction}' which references a managed bean 'missingBean', but no managed bean by this name can be found.%%
<h:commandButton value="Home" actionListener="#{missingBean.myActionListener}" />
%%(color:red)junit.framework.AssertionFailedError: C:/work/workspace/jsf-unit/src/views/home.xhtml has an EL expression '#{missingBean.myActionListener}' which references a managed bean 'missingBean', but no managed bean by this name can be found.%%
<h:commandButton value="Home">
<f:actionListener binding="#{missingBean.myOtherActionListener}" />
</h:commandButton>
%%(color:red)junit.framework.AssertionFailedError: C:/work/workspace/jsf-unit/src/views/home.xhtml has an EL expression '#{missingBean.myOtherActionListener}' which references a managed bean 'missingBean', but no managed bean by this name can be found.%%
Do any of your templates or JSPs have EL expressions for nonexistent managed bean actions or action listeners?
<h:commandButton value="Home" action="#{managedBean.myAction}" />
%%(color:red)junit.framework.AssertionFailedError: C:/work/workspace/jsf-unit/src/views/home.xhtml contains EL #{managedBean.myAction}, but managed bean managedBean->org.jboss.jsfunit.demo.ManagedBean does not have a myAction method.%%
<h:commandButton value="Home" actionListener="#{managedBean.myActionListener}" />
%%(color:red)junit.framework.AssertionFailedError: C:/work/workspace/jsf-unit/src/views/home.xhtml contains EL #{managedBean.myActionListener}, but managed bean managedBean->org.jboss.jsfunit.demo.ManagedBean does not have a myActionListener method.%%
<h:commandButton value="Home">
<f:actionListener binding="#{managedBean.myOtherMissingActionListener}" />
</h:commandButton>
%%(color:red)junit.framework.AssertionFailedError: C:/work/workspace/jsf-unit/src/views/home.xhtml contains EL #{managedBean.myOtherMissingActionListener}, but managed bean managedBean->org.jboss.jsfunit.demo.ManagedBean does not have a myOtherMissingActionListener method.%%
Extending org.jboss.jsfunit.analysis.AbstractFacesConfigTestCase
%%(color:green)
public class FacesConfigTestCase extends AbstractFacesConfigTestCase {
private static Set<String> paths = new HashSet() {{
add("C:/work/workspace/jsf-unit/src/faces-config.xml");
}};
public FacesConfigTestCase() {
super(paths);
}
}
%%
Are all of your session and application scoped beans Serializable?
<managed-bean>
<description>
package com.foo.demo;
public class ShoppingCart { }
</description>
<managed-bean-name>shoppingCart</managed-bean-name>
<managed-bean-class>
com.foo.demo.ShoppingCart
</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
%%(color:red)junit.framework.AssertionFailedError: Managed bean 'shoppingCart'
is in session scope, so it needs to implement interface java.io.Serializable%%
Invalid Managed Bean Scope?
<managed-bean>
<managed-bean-name>shoppingCart</managed-bean-name>
<managed-bean-class>
com.foo.demo.ShoppingCart
</managed-bean-class>
<managed-bean-scope>reqest</managed-bean-scope>
</managed-bean>
%%(color:red)junit.framework.AssertionFailedError: Managed bean 'shoppingCart' in C:/work/workspace/jsf-unit/src/faces-config.xml has an invalid scope 'reqest'
%%
Missing Managed Bean Class?
<managed-bean>
<managed-bean-name>shoppingCart</managed-bean-name>
<managed-bean-class>
com.foo.demo.ShopingCart
</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
%%(color:red)
junit.framework.AssertionFailedError: Could not load class
com.foo.demo.ShopingCart? for element managed-bean-class %%
Faces Config Class Inheritance?
<converter>
<description>com.foo.demo.~CurrencyConverter is a POJO</description>
<converter-id>currencyConverter</converter-id>
<converter-class>com.foo.demo.~CurrencyConverter</converter-class>
</converter>
%%(color:red)
junit.framework.AssertionFailedError: In C:/work/workspace/jsf-unit/src/faces-config.xml',
com.foo.demo.CurrencyConverter for element converter-class should be a javax.faces.convert.Converter%%
This works for the following elements as well:
action-listener
navigation-handler
variable-resolver
property-resolver
view-handler
state-manager
faces-context-factory
application-factory
lifecycle-factory
render-kit-factory
component-class
converter-class
validator-class
render-kit-class
renderer-class
phase-listener
converter-for-class
Missing Setter Methods?
<managed-bean>
<managed-bean-name>shoppingCart</managed-bean-name>
<managed-bean-class>
com.foo.demo.~ShoppingCart
</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
<managed-property>
<description>javax.faces.el.~MethodNotFoundException</description>
<property-name>tax</property-name>
<value>5</value>
</managed-property>
</managed-bean>
%%(color:red)
junit.framework.AssertionFailedError: The managed bean 'shoppingCart'
has a managed property called 'tax', but com.foo.demo.ShoppingCart has no method setTax(?)%%
Duplicate Managed Bean Names?
<managed-bean>
<managed-bean-name>shoppingCart</managed-bean-name>
<managed-bean-class>
com.foo.demo.ShoppingCart
</managed-bean-class>
<managed-bean-scope>application</managed-bean-scope>
</managed-bean>
<managed-bean>
<managed-bean-name>shoppingCart</managed-bean-name>
<managed-bean-class>
com.foo.demo.duplicate.ShoppingCart
</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
%%(color:red)
junit.framework.AssertionFailedError: The managed bean 'shoppingCart' in
'C:/work/workspace/jsf-unit/src/faces-config.xml' is duplicated.
Look for a managed bean w/ the same name in 'C:/work/workspace/jsf-unit/src/faces-config.xml'%%
Extending org.jboss.jsfunit.analysis.AbstractTldTestCase
%%(color:green)
public class TldTestCase extends AbstractTldTestCase {
private static Set<String> paths = new HashSet() {{
add("C:/work/workspace/jsf-unit/src/demo.tld");
}};
public TldTestCase() {
super(paths);
}
}
%%
Correct Tag Attribute Types?
<tag>
<name>checkoutTag</name>
<tag-class>com.foo.demo.CheckoutTag</tag-class>
<body-content>empty</body-content>
<attribute>
<name>itemCount</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
<type>java.lang.Integer</type>
</attribute>
</tag>
%%(color:red)
junit.framework.AssertionFailedError: Tag 'checkoutTag' in TLD 'demo'
is a javax.faces.webapp.UIComponentTag. Becuase it is a JSF 1.1 tag,
each tag attribute must be of type java.lang.String, however attribute 'itemCount'
is of type java.lang.Integer. See JSF Spec 1.2 section 9.3.1.1 for more information.%%
Unique Tag Names?
<tag>
<name>checkoutTag</name>
<tag-class>com.foo.demo.CheckoutTag</tag-class>
<body-content>empty</body-content>
</tag>
<tag>
<name>checkoutTag</name>
<tag-class>com.foo.demo.duplicate.CheckoutTag</tag-class>
<body-content>empty</body-content>
</tag>
%%(color:red)
junit.framework.AssertionFailedError: Tag 'checkoutTag' occurs
in tag library 'demo' more than once %%
Correct Tag Inheritance?
<tag>
<name>checkoutTag</name>
<!-- Just a POJO -->
<tag-class>com.foo.demo.CheckoutTag</tag-class>
<body-content>empty</body-content>
</tag>
%%(color:red)
junit.framework.AssertionFailedError: class com.foo.demo.CheckoutTag
configured in demo needs to be a javax.faces.webapp.UIComponentTag or a javax.faces.webapp.UIComponentTagBase%%
Unique Tag Attributes?
<tag>
<name>checkoutTag</name>
<tag-class>com.foo.demo.CheckoutTag</tag-class>
<body-content>empty</body-content>
<attribute>
<name>itemCount</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
<type>java.lang.String</type>
</attribute>
<attribute>
<name>itemCount</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
<type>java.lang.String</type>
</attribute>
</tag>
%%(color:red)
junit.framework.AssertionFailedError: Attribute itemCount
in demo:checkoutTag is duplicated. %%
Dependencies
AbstractFacesConfigTestCase has a runtime dependency on the JSF 1.2 API (even if you are using JSF 1.1), such as myfaces-api-1.2.0.jar
AbstractTldTestCase has a runtime dependency on maven-taglib-checker
, clogging
and jsp-api-2.1.jar
Referenced by:
JSFUnitDocumentation
Other languages:
Log in to make links between pages