Clone wiki

Java EE 6-Galleria / TestingTheApplicationLayer

Testing the Application Layer

The application layer is tested through the use of the EJBContainer API. This API allows you to bootstrap an embedded instance of an EJB container, where the application layer and it's dependencies would be deployed. Once deployed, the tests would obtain references to the deployed EJBs and perform operations on them.

The tests are run using the Maven failsafe plugin, instead of the surefire plugin, as the deployment of the EJBs is CPU and disk intensive. This makes for slower tests, and hence the tests are not run during the unit testing phase, but instead in the integration testing phase. Also, these tests are true integration tests where in the real application layer, is deployed with the JPA repositories to use the real persistent unit, against a more-or-less real container.

It should be noted that the application layer of this application enforces security and transaction control. The security constraints are imposed through the @RolesAllowed annotations on the services, which in turn rely on JAAS. The JAAS realm for the test, is configured via the use of a specialized domain.xml file that is used to configure the embedded GlassFish container. The domain.xml file also contains the JNDI datasource and the backing connection pool, which is also used by the JAAS JDBC realm.

What do the tests do?

Every test extends the AbstractIntegrationTest class. This class outlines the overall behavior of the test lifecycle:

  • An instance of an EJBContainer is created in the @BeforeClass method, unless it has already been created as part of the Test suite. This initializes the embedded EJB container, and deploys the EJBs found in the classpath.
  • DbUnit is used to reset the contents of the test database in the @Before method, in the same manner as performed in the tests for the JPA repositories.
  • The EJBContainer is eventually shutdown in the @AfterClass method, unless it is the Test suite that is responsible for shutting down the container.

During test startup, references are obtained to Context and DataSource instances. Once the application is deployed, references to EJB instances required by the tests can be obtained through the Context instance. The DataSource instance is used to obtain Connection instances that can be used to execute SQL statements during the assertion phase of a test.

Most tests involve obtaining references to EJB instances, through the Context, followed by operations performed on these EJBs. Assertions are then performed on the objects returned by the EJBs, or on the database (through a Connection obtained from the DataSource.

Simulating an authenticated user

Certain tests involve setting up a login context, wherein the request to the application layer would be made, as if an authenticated user were doing so. Since the integration tests do not involve deployment of a web application, where a user login would be simulated to obtain this context, we'll use certain internal GlassFish APIs to setup this context. Setting up the login context for a test is quite simple - the ProgrammaticLogin class allows you to provide the credentials and specify a JAAS realm to use. The embedded GlassFish container uses the credentials to attempt a login against the specified realm.

ProgrammaticLogin login = new ProgrammaticLogin();
login.login(TEST_USER_ID, TEST_PASSWORD, "GalleriaRealm", true);

If successful, the created login context can be used to make invocations on EJBs that require such a context. When the context needs to be discarded (for instance, a new context needs to be created), then one can invoke the logout method of the ProgrammaticLogin class:

ProgrammaticLogin login = new ProgrammaticLogin();
login.login(TEST_USER_ID, TEST_PASSWORD, "GalleriaRealm", true);
//... do some magic