2 Replies Latest reply on Nov 23, 2012 11:04 AM by paul.robinson

    ATE: Transaction behavior in @Before and @After

    paul.robinson

      Pulling out into a separate discussion from: https://community.jboss.org/message/777483

       

      Problem

      Currently the Arquillian Transaction Extension (ATE) starts the transaction before invoking @Before and then completes it after @After is invoked. This has the following issues/implications:

       

      1. The same transaction is used for the @Begin, @Test and @After methods.
      2. You can't use the @After method to undo any work. If you update a resource in the test and then negate the update in @After, you would leave nothing to commit when the transaction commits.
      3. You can't access any data that is only available after the transaction commits. For example, you may need to consume a message, produced by the test, in order to tidy up from the test. This message will not be available until the after the transaction has committed, and thus not available in the @After.
      4. You can't Assert the environment after the transaction commits.

       

      Solution

      From the above discussion with Aslak, I think this is the solution that could solve the above issues:

       

      Have the transaction just span the @Test method by default. Allow @Transactional to be added to @Before and @After, but use a separate transaction for each, which completes at the end of the method. We could also add an API to allow the transaction to achieve the current behavior of spanning @Before, @Test and @After. This would need some thought as I can think of a few issues that would need addressing.

       

      Remaining Issues

      Is @After the right place to run assertions? Ideally you would run assertions in the @Test method, but this isn't possible if you want to assert something after the transaction completes. Assertions in @After would need to be general enough to hold for all @Test methods in the class. I think this still leaves the issue open for test specific assertions.

       

      Here's an example of where I use @Test specific assertions after a transaction completes: https://github.com/jbosstm/narayana/blob/master/txframework/src/test/java/org/jboss/narayana/txframework/functional/BACoordinatorCompletionTest.java. In this test I have a service that participates in a transaction. The service logs what protocol messages it received when the termination protocol was invoked. After the transaction has completed, I assert that the right protocol messages were received and in the right order.

        • 1. Re: ATE: Transaction behavior in @Before and @After
          aslak

          @After is a good place for clean up, but not for Assertions.

           

          In the case where manual outside of transaction Assertions are required we should provide a TransactionManager injection or similar.

           

          // optionally define provider on injection if only 
          // one is wanted within this TestClass but multiple on cp?
          @ArquillianResource("provider")
          private TransactionManager tm;
          
          
          @Test
          public void shouldStoreToDB() {
            // provider (JTA|WS-X|Spring) optionally 
            // argument if only one provider on cp?
            try {
          
                    tm.begin("manager", "provider");
          
                    doStuff();
          
                    tm.commit("manager", "provider");
          
            } catch(Exception e) {
              tm.rollback("manager", "provider");
            }
            assertStuff():
          }
          
          
          @Test
          public void shouldStoreToDbWithCallable() {
          
          
                    // support transactional block to avoid try catch 
          
                    X x = tm.run("manager", "provider", 
                              new Callable<X>{
                                        public X call() {
                                                  doSomethingTransactional();
                                                  return someTransactedObject();
                                        }
                    });
          
                    assertStuff();
          }
          
          
          • 2. Re: ATE: Transaction behavior in @Before and @After
            paul.robinson

            Aslak,

             

            Agreed, a TransactionManager injection is probably the way to go to solve the "Remaining Issues" from above. See here for where I put the discussion on that: https://community.jboss.org/message/778110

             

            Paul.