35.3. Integration testing Seam application user interactions
It is more difficult to emulate user interactions, and to place assertions appropriately. Some test frameworks let us test the whole application by reproducing user interactions with the web browser. These are useful, but not appropriate during development.
SeamTest
lets you write scripted tests in a simulated JSF environment. A scripted test reproduces the interaction between the view and the Seam components, so you play the role of the JSF implementation during testing. You can test everything but the view with this approach.
Consider a JSP view for the component we unit tested above:
<html> <head> <title>Register New User</title> </head> <body> <f:view> <h:form> <table border="0"> <tr> <td>Username</td> <td><h:inputText value="#{user.username}"/></td> </tr> <tr> <td>Real Name</td> <td><h:inputText value="#{user.name}"/></td> </tr> <tr> <td>Password</td> <td><h:inputSecret value="#{user.password}"/></td> </tr> </table> <h:messages/> <h:commandButton type="submit" value="Register" action="#{register.register}"/> </h:form> </f:view> </body> </html>
We want to test the registration functionality of our application (that is, what happens when a user clicks the Register button). We will reproduce the JSF request life cycle in an automated TestNG test:
public class RegisterTest extends SeamTesFt { @Test public void testRegister() throws Exception { new FacesRequest() { @Override protected void processValidations() throws Exception { validateValue("#{user.username}", "1ovthafew"); validateValue("#{user.name}", "Gavin King"); validateValue("#{user.password}", "secret"); assert !isValidationFailure(); } @Override protected void updateModelValues() throws Exception { setValue("#{user.username}", "1ovthafew"); setValue("#{user.name}", "Gavin King"); setValue("#{user.password}", "secret"); } @Override protected void invokeApplication() { assert invokeMethod("#{register.register}").equals("success"); } @Override protected void renderResponse() { assert getValue("#{user.username}").equals("1ovthafew"); assert getValue("#{user.name}").equals("Gavin King"); assert getValue("#{user.password}").equals("secret"); } }.run(); } ... }
Here, we extend
SeamTest
to provide a Seam environment for our components, and our test script is written as an anonymous class that extends SeamTest.FacesRequest
, which provides an emulated JSF request life cycle. (There is also a SeamTest.NonFacesRequest
for testing GET requests.) Our code includes methods named for various JSF phases, to emulate the calls that JSF would make to our components. We have then included various assertions.
The Seam example applications include integration tests demonstrating more complex cases. You can run these tests with Ant, or with the TestNG plug-in for Eclipse:
35.3.1. Configuration
If you created your project with seam-gen, you can start writing tests immediately. Otherwise, you must first set up a testing environment in a build tool such as Ant, Maven, or Eclipse.
You will require at least the following dependencies:
Table 35.1.
Group ID | Artifact ID | Location in Seam |
---|---|---|
org.jboss.seam.embedded | hibernate-all | lib/test/hibernate-all.jar |
org.jboss.seam.embedded | jboss-embedded-all | lib/test/jboss-embedded-all.jar |
org.jboss.seam.embedded | thirdparty-all | lib/test/thirdparty-all.jar |
org.jboss.seam.embedded | jboss-embedded-api | lib/jboss-embedded-api.jar |
org.jboss.seam | jboss-seam | lib/jboss-seam.jar |
org.jboss.el | jboss-el | lib/jboss-el.jar |
javax.faces | jsf-api | lib/jsf-api.jar |
javax.el | el-api | lib/el-api.jar |
javax.activation | javax.activation | lib/activation.jar |
Do not put the compile-time JBoss Enterprise Application Platform dependencies from
lib/
(such as jboss-system.jar
) on the classpath, as this will prevent Embedded JBoss from booting. Add dependencies such as Drools and jBPM as you require them.
You must include the
bootstrap/
directory on the classpath, since it contains the configuration for Embedded JBoss.
You must also include your built project, tests, and the
jar
for your test framework on the classpath, as well as configuration files for JPA and Seam. Seam asks Embedded JBoss to deploy any resource (JAR or directory) with seam.properties
in its root. If the structure of the directory containing your built project does not resemble that of a deployable archive, you must include seam.properties
in each resource.
By default, a generated project uses the
java:/DefaultDS
(a built in HSQL datasource in Embedded JBoss) for testing. To use another datasource, place the foo-ds.xml
into bootstrap/deploy
directory.