6 Replies Latest reply on Feb 26, 2013 1:42 PM by Marcos Portela

    How to test for application exceptions Arquillian, EJB, JUnit

    Chris Ritchie Newbie

      I am having problems testing application exceptions thrown within an EJB. I am using JUnit, Arquillian, JBoss. I may have a missunderstanding how EJB's should be programmed/tested. This is my first posting so if I need to clarify anything, or give more details, or provide more code, please let me know. I would appreciate any suggestions on how to test for application exceptions in an EJB.

       

      When a runtime exception is thrown within the EJB, the transaction is destroyed, and a TransactionRequiredException is thrown. Any subsequent test (that passes when run as a single test) fails with the following exception:

       

        javax.transaction.NotSupportedException: BaseTransaction.checkTransactionState - ARJUNA016051: thread is already associated with a transaction!

       

       

      Secondly if I try to assert that the exception thrown is of type TransactionRequiredException, then i get the following exception:

       

        java.lang.Exception: Unexpected exception, expected<javax.persistence.TransactionRequiredException> but was<java.lang.AssertionError>

       

       

      The important code is below

       

      The test class:

       

       

      @RunWith(Arquillian.class)

      public class PlayerDomainTestCase extends PersistenceTest {

       

          @Deployment

          public static Archive<?> createDeployment() {

              return ArchiveFactory.getFullArchive();

          }

       

          @PersistenceContext
          protected EntityManager em;

          @Inject
          protected UserTransaction utx;   

          @Before
          public void preparePersistenceTest() throws Exception {
              beginTransaction();
          }

           @After
           public void commitTransaction() throws Exception {
               utx.commit();
           }

           protected void beginTransaction() throws Exception {
               utx.begin();
               em.joinTransaction();
           }

           @Test(expected=TransactionRequiredException.class)
           public void testRetirePlayerOnFutureDateBean() throws Exception {

               // SETUP
               Player player = playerDao.findAll().get(0);

               // TEST - method throws IllegalArgumentException if the date is after today...
               playerBean.retirePlayer(player.getId(), new DateTime().plusDays(1));

               // ASSERT - TransactionRequiredException
           }

           @Test
           public void testSavePlayerProfile() throws Exception {
               // another test using an EJB, which passes if above test is commented out
               // its fails only when the previous test has caused the destruction of the transaction
           }

      }

       

      The EJB is below:

       

       

      @Stateless

      @LocalBean

      @Remote(IPlayer.class)

      public class PlayerBean implements IPlayer {

       

          @Override

          public ResponseDto retirePlayer(Integer playerId, DateTime retireDate) {

             

              ResponseDto responseDto = new ResponseDto();

              try {

                  Player player = playerDao.findById(playerId);

                  //method below throws IllegalArgException is date is invalid.

                  retirePlayerService.retire(player, retireDate);

              } catch (Exception e) {

                  logger.error(e.getCause());

                  responseDto.setErrorMessage(e.getCause().getMessage());

              }

              return responseDto;

             

          }

      }

        • 1. Re: How to test for application exceptions Arquillian, EJB, JUnit
          Norsay Norsay Newbie

          Hi Chris

           

          First, welcome to this forum

           

          From my experiece I would say it's better to let the container manage the transaction. Otherwise you are not sure, same behavior will happen in real "production" world. I have set up a testing environment with container managed transaction which works very fine....

           

          So I would suggest to remove all UserTransaction stuff and transaction handling to ensure "real life" container behavior... Then you should be able to test your application exceptions as well.

           

          Hope this helps as a little inspiration

           

          Cheers, norsay

          • 2. Re: How to test for application exceptions Arquillian, EJB, JUnit
            Chris Ritchie Newbie

            Hi Norsay,

             

            Thanks for your response. I removed all the UserTransaction code, like you suggested, but then got exceptions on the set up code. I agree that is is better to allow the test line of code to run in the transaction managed by the container, so I have updated as below, so the line of code being tested, does have its transaction managed by the container.

             

                

                @Test

                public void testRetirePlayerOnFutureDateBean() throws Exception {

                   

                    // SETUP

                    Player player = playerDao.findAll().get(0);

             

                    //no transaction so  the behaviour is as close to production as possible

                    commitTransaction();

                           

                    // TEST - use tomorrows date

                    ResponseDto response = playerBean.retirePlayer(player.getId(), new DateTime().plusDays(1));

             

                    // ASSERT

                    Assert.assertTrue("Response should have errors!", response.hasErrors());

             

                }

             

             

            Thanks again for your response.

             

            Chris

            • 3. Re: How to test for application exceptions Arquillian, EJB, JUnit
              Norsay Norsay Newbie

              Maybe I'm able to provide you a few code snippets... However I can't promis to deliver, because I'm pretty busy and have to collect the necessary information in my code first...

               

              Cheers, norsay

              • 4. Re: How to test for application exceptions Arquillian, EJB, JUnit
                Norsay Norsay Newbie

                Just changed my mind I was able to c&p some code, which does not compile but illustrates how I'm doing writting my tests... hope this helps..

                 

                {code}

                @RunWith(Arquillian.class)

                @UsingDataSet("SimpleTestData.xls")

                public class SimpleTest {

                 

                 

                    private MyDao myDao;

                 

                 

                    @PersistenceContext()

                    private EntityManager entityManager;

                 

                 

                    protected EntityManager getEntityManager() {

                        return this.entityManager;

                    }

                 

                    @Deployment

                    public static JavaArchive createDeployment() {

                        JavaArchive archive = ShrinkWrap.create(JavaArchive.class);

                 

                 

                        // add you classes to the archive here...

                        archive.addPackage("mypackage.xy.");

                        ....

                 

                 

                        // add resources

                        archive.addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");

                        archive.addAsResource("META-INF/persistence.xml", "META-INF/persistence.xml");

                 

                 

                        return archive;

                    }

                 

                    @Before

                    public void setUp() throws Exception {

                        this.myDao = new MyDao(getEntityManager());

                    }

                 

                    @Test

                    public void findAll() {

                        List<My> result = this.myDao.findAll();

                        Assert.assertEquals(46, result.size());

                    }

                 

                    @Test(expect=IllegalArgumentException.class)

                    public void findAll() {

                        List<My> result = this.myDao.save(null);

                    }

                }

                {code}

                 

                 

                and your pom.xml should look similar to this:

                 

                {code:xml}

                ...

                        <profile>

                            <id>arquillian-jbossas-managed</id>

                            <activation>

                                <activeByDefault>true</activeByDefault>

                            </activation>

                            <build>

                                <plugins>

                                    <plugin>

                                        <artifactId>maven-dependency-plugin</artifactId>

                                    </plugin>

                                </plugins>

                            </build>

                            <dependencies>

                                <dependency>

                                    <groupId>org.jboss.spec</groupId>

                                    <artifactId>jboss-javaee-6.0</artifactId>

                                    <version>${jboss-javaee-version}</version>

                                    <type>pom</type>

                                    <scope>provided</scope>

                                </dependency>

                                <dependency>

                                    <groupId>org.jboss.as</groupId>

                                    <artifactId>jboss-as-arquillian-container-managed</artifactId>

                                    <version>${jboss-as-arquillian-container-managed-version}</version>

                                    <scope>test</scope>

                                </dependency>

                            </dependencies>

                        </profile>

                ...

                {code}

                 

                BTW: I think you should avoid transaction commits in the test. Instead use getEntityManager().flush() for example...

                1 of 1 people found this helpful
                • 5. Re: How to test for application exceptions Arquillian, EJB, JUnit
                  Chris Ritchie Newbie

                  Hi Norsay,

                   

                  Thanks for the time you have spent on this example. I now flush the cache rather than commit.

                  • 6. Re: How to test for application exceptions Arquillian, EJB, JUnit
                    Marcos Portela Newbie

                    Hi, Chris Ritchie,

                     

                    I suggest you the use of arquillian-persistence-extension for purpose of persistence tests.  So, you garantees the control of datasets used in your tests. See this link, for more details: https://docs.jboss.org/author/display/ARQ/Persistence

                    You can configure severals datasets that will feed the database.

                     

                    Another Link: http://arquillian.org/blog/tags/persistence/

                     

                    See the snippet below:

                     

                    @Test

                    @Cleanup(phase=TestExecutionPhase.NONE)

                    @ApplyScriptBefore("imports/import-data-for-teste-support.sql")

                      public void testAnaliser() {

                            final String response = "140804.68,132620.74,0,0,0,0,0,0,0,2,2,30.00,0";

                            final List<ResultTest> results = analiser.analiserForResponse(response);           

                            assertThat(results, hasSize(13));

                    }

                     

                    Disables default configuration for cleanup: https://github.com/arquillian/arquillian-extension-persistence/blob/master/api/src/main/java/org/jboss/arquillian/persistence/TestExecutionPhase.java