You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomee.apache.org by Jack Cox <jc...@captechventures.com> on 2008/02/12 15:22:16 UTC

Transactions controlled by Unit Tests

Is there a way in the 'out-of-container' testing paradigm with openejb for
the unit test method to control the demarcation of transactions?  

Here's the use case:
1) The unit test is doing entity bean testing, calling various methods on
the entity facade to test CRUD operations.
2) The unit test needs to demarcate transactions so that it can insert,
delete, then attempt to retrieve deleted entities.  Of course the last
retrieval should fail because the entity is deleted.  
3) But, JPA has the interesting behavior that deleted entities continue to
be accessible within the deleting transaction.
4) Therefore, the unit test needs to demarcate a transaction around the
delete so that the entity is really removed prior to the last retrieval
test.

So, how can one demarcate transactions within a junit test case?

Thanks,

Jack

-- 
View this message in context: http://www.nabble.com/Transactions-controlled-by-Unit-Tests-tp15434029p15434029.html
Sent from the OpenEJB User mailing list archive at Nabble.com.


Re: Transactions controlled by Unit Tests

Posted by Alexander Saint Croix <sa...@gmail.com>.
In case it needs stating again, thanks to David Blevins for showing me how
to do this--I'm working on my app again, and making forward progress after
one tough month of test hangups.

--
Alex

Re: Transactions controlled by Unit Tests

Posted by Alexander Saint Croix <sa...@gmail.com>.
Jack,

Funny you should ask--I was working on the same thing last week.
http://weblogs.java.net/blog/saintx/archive/2008/02/lambda_function.htmlshows
a good start on how to do this.

The transactions are controlled by a stateless session bean in the base
class, and the method blocks of the test case are broken down into units of
work, then fed into this session bean as Callable objects.  Each callable is
wrapped in its own transaction.  The "getCalls" method is abstract in the
base and gets called by the "test..." method in the base class, so extending
the base requires implementing "getCalls".

Now, the way I do my CRUD tests is slightly different.  They look like this:

public class CRUDTest extends CascadeTestBase {
>
>     public Callable[] getCalls() {
>         return toCallableArray(
>         getCRUD(new Address(), "Address"),
>         getCRUD(new AssociatedAddress(), "AssociatedAddress"),
>         getCRUD(new EmailAddress(), "EmailAddress"),
>         getCRUD(new GeographicAddress(), "GeographicAddress"),
>         getCRUD(new ISOCountryCode(), "ISOCountryCode"),
>         getCRUD(new Locale(), "Locale"),
>         getCRUD(new TelecomAddress(), "TelecomAddress"),
>         getCRUD(new WebPageAddress(), "WebPageAddress"),
>         getCRUD(new AssignedResponsibility(), "AssignedResponsibility"),
>         getCRUD(new Capability(), "Capability"),
>         getCRUD(new PartyRelationship(), "PartyRelationship"),
>         getCRUD(new PartyRelationshipType(), "PartyRelationshipType"),
>         getCRUD(new PartyRole(), "PartyRole"),
>         getCRUD(new PartyRoleType(), "PartyRoleType"),
>         getCRUD(new Responsibility(), "Responsibility"),
>         getCRUD(new Organization(), "Organization"),
>         getCRUD(new OrganizationName(), "OrganizationName"),
>         getCRUD(new Party(), "Party"),
>         getCRUD(new PartySignature(), "PartySignature"),
>         getCRUD(new Person(), "Person"),
>         getCRUD(new PersonName(), "PersonName"),
>         getCRUD(new Binding(), "Binding"),
>         getCRUD(new BindingValue(), "BindingValue"),
>         getCRUD(new BindingType(), "BindingType"));
>     }
>
>     private <T extends Archetype> Callable[] getCRUD(T stem, String
> table){
>         return new Tester<T>(stem, table).getCalls();
>     }
>
>     private Callable[] toCallableArray(Callable[]... array) {
>         final int l = array.length;
>         final int l2 = 3;
>         Callable[] result = new Callable[l * l2];
>
>         for (int i = 0; i < l; i++) {
>             Callable[] subarray = array[i];
>             for (int j = 0; j < l2; j++) {
>                 result[i * l2 + j] = subarray[j];
>             }
>         }
>         return result;
>     }
>
>     private class Tester<T extends Archetype> {
>         private Retriever<T> bean;
>         private T o1, o2;
>         private String table;
>         private long ID;
>
>         public Tester(T o1, String table) {
>             this.table = table;
>             this.o1 = o1;
>         }
>
>         public Callable phase01() {
>             return new Callable() {
>                 public Object call() {
>
>                     // CREATE
>                     assertEquals(0, o1.getID());
>                     mgr.persist(o1);
>                     mgr.flush();
>                     ID = o1.getID();
>                     return null;
>                 }
>             };
>         }
>
>         public Callable phase02() {
>             return new Callable() {
>                 public Object call() {
>
>                     // READ & UPDATE
>                     assertEquals(
>                             "Failed size check for table named \""
>                                     + table + "\"",
>                             1,
>                             mgr.sizeOf(table));
>
>                     bean = new Retriever<T>(table, ID);
>                     o2 = bean.fetch();
>                     Assert.assertNotNull(o2);
>                     o2.setName("name of bean");
>                     o2 = null;
>                     return null;
>                 }
>             };
>         }
>
>         public Callable phase03() {
>             return new Callable() {
>                 public Object call() {
>
>                     // VERIFY UPDATE
>                     assertEquals(1, mgr.sizeOf(table));
>                     bean = new Retriever<T>(table, ID);
>                     o2 = bean.fetch();
>                     assertNotNull(o2);
>                     assertEquals("name of bean", o2.getName());
>
>                     // DESTROY
>                     mgr.remove(o2);
>                     mgr.flush();
>                     assertEquals(0, mgr.sizeOf(table));
>                     return null;
>                 }
>             };
>         }
>
>         /**
>          * Retrieve units of work for this CRUD test block
>          * @return Callable[] units of work
>          */
>         public Callable[] getCalls() {
>             return new Callable[]{
>                     phase01(),
>                     phase02(),
>                     phase03()
>             };
>         }
>     }
>


Hope this helps,
--
Alexander R. Saint Croix




On Feb 12, 2008 8:22 AM, Jack Cox <jc...@captechventures.com> wrote:

>
> Is there a way in the 'out-of-container' testing paradigm with openejb for
> the unit test method to control the demarcation of transactions?
>
> Here's the use case:
> 1) The unit test is doing entity bean testing, calling various methods on
> the entity facade to test CRUD operations.
> 2) The unit test needs to demarcate transactions so that it can insert,
> delete, then attempt to retrieve deleted entities.  Of course the last
> retrieval should fail because the entity is deleted.
> 3) But, JPA has the interesting behavior that deleted entities continue to
> be accessible within the deleting transaction.
> 4) Therefore, the unit test needs to demarcate a transaction around the
> delete so that the entity is really removed prior to the last retrieval
> test.
>
> So, how can one demarcate transactions within a junit test case?
>
> Thanks,
>
> Jack
>
> --
> View this message in context:
> http://www.nabble.com/Transactions-controlled-by-Unit-Tests-tp15434029p15434029.html
> Sent from the OpenEJB User mailing list archive at Nabble.com.
>
>

Re: Transactions controlled by Unit Tests

Posted by Jack Cox <jc...@captechventures.com>.
David,

Thanks for the clear example, it now makes sense.  I like the approach since
it doesn't require modifying the bean under test.

-Jack


David Blevins wrote:
> 
> Here,  http://cwiki.apache.org/OPENEJBx30/unit-testing-transactions.html
> 
> I wrote up a doc for you better describing the pattern I created for  
> Alex.  It shows usage for transactions, but the same pattern can be  
> used for security as well.
> 
> That approach works great and still keeps you free of any OpenEJB- 
> specific code in your test cases.
> 
> If you don't have any issues with your test cases extending an OpenEJB  
> specific TestCase implementation then I'm pretty sure we could find a  
> way to support @TransactionAttribute and @RunAs on the test methods  
> themselves (as well as dependency injection).  If that sounds  
> attractive to you, I'll create a JIRA for it.  We'd probably implement  
> it as syntactic sugar on the above approach.
> 
> -David
> 
> On Feb 12, 2008, at 8:39 AM, Jack Cox wrote:
> 
>>
>> I'll break etiquette and reply to my own post.
>>
>> I was mistaken (i.e. I'm stupid) regarding the delete operation.   
>> The entity
>> does disappear from the JPA context.
>>
>> That not withstanding, I still have need to control the transaction
>> demarcation from the junit test case.
>>
>> Jack
>>
>>
>> Jack Cox wrote:
>>>
>>> Is there a way in the 'out-of-container' testing paradigm with  
>>> openejb for
>>> the unit test method to control the demarcation of transactions?
>>>
>>> Here's the use case:
>>> 1) The unit test is doing entity bean testing, calling various  
>>> methods on
>>> the entity facade to test CRUD operations.
>>> 2) The unit test needs to demarcate transactions so that it can  
>>> insert,
>>> delete, then attempt to retrieve deleted entities.  Of course the  
>>> last
>>> retrieval should fail because the entity is deleted.
>>> 3) But, JPA has the interesting behavior that deleted entities  
>>> continue to
>>> be accessible within the deleting transaction.
>>> 4) Therefore, the unit test needs to demarcate a transaction around  
>>> the
>>> delete so that the entity is really removed prior to the last  
>>> retrieval
>>> test.
>>>
>>> So, how can one demarcate transactions within a junit test case?
>>>
>>> Thanks,
>>>
>>> Jack
>>>
>>>
>>
>> -- 
>> View this message in context:
>> http://www.nabble.com/Transactions-controlled-by-Unit-Tests-tp15434029p15434676.html
>> Sent from the OpenEJB User mailing list archive at Nabble.com.
>>
>>
> 
> 
> 

-- 
View this message in context: http://www.nabble.com/Transactions-controlled-by-Unit-Tests-tp15434029p15458937.html
Sent from the OpenEJB User mailing list archive at Nabble.com.


Re: Transactions controlled by Unit Tests

Posted by David Blevins <da...@visi.com>.
Here,  http://cwiki.apache.org/OPENEJBx30/unit-testing-transactions.html

I wrote up a doc for you better describing the pattern I created for  
Alex.  It shows usage for transactions, but the same pattern can be  
used for security as well.

That approach works great and still keeps you free of any OpenEJB- 
specific code in your test cases.

If you don't have any issues with your test cases extending an OpenEJB  
specific TestCase implementation then I'm pretty sure we could find a  
way to support @TransactionAttribute and @RunAs on the test methods  
themselves (as well as dependency injection).  If that sounds  
attractive to you, I'll create a JIRA for it.  We'd probably implement  
it as syntactic sugar on the above approach.

-David

On Feb 12, 2008, at 8:39 AM, Jack Cox wrote:

>
> I'll break etiquette and reply to my own post.
>
> I was mistaken (i.e. I'm stupid) regarding the delete operation.   
> The entity
> does disappear from the JPA context.
>
> That not withstanding, I still have need to control the transaction
> demarcation from the junit test case.
>
> Jack
>
>
> Jack Cox wrote:
>>
>> Is there a way in the 'out-of-container' testing paradigm with  
>> openejb for
>> the unit test method to control the demarcation of transactions?
>>
>> Here's the use case:
>> 1) The unit test is doing entity bean testing, calling various  
>> methods on
>> the entity facade to test CRUD operations.
>> 2) The unit test needs to demarcate transactions so that it can  
>> insert,
>> delete, then attempt to retrieve deleted entities.  Of course the  
>> last
>> retrieval should fail because the entity is deleted.
>> 3) But, JPA has the interesting behavior that deleted entities  
>> continue to
>> be accessible within the deleting transaction.
>> 4) Therefore, the unit test needs to demarcate a transaction around  
>> the
>> delete so that the entity is really removed prior to the last  
>> retrieval
>> test.
>>
>> So, how can one demarcate transactions within a junit test case?
>>
>> Thanks,
>>
>> Jack
>>
>>
>
> -- 
> View this message in context: http://www.nabble.com/Transactions-controlled-by-Unit-Tests-tp15434029p15434676.html
> Sent from the OpenEJB User mailing list archive at Nabble.com.
>
>


Re: Transactions controlled by Unit Tests

Posted by Jack Cox <jc...@captechventures.com>.
I'll break etiquette and reply to my own post.

I was mistaken (i.e. I'm stupid) regarding the delete operation.  The entity
does disappear from the JPA context.  

That not withstanding, I still have need to control the transaction
demarcation from the junit test case.

Jack


Jack Cox wrote:
> 
> Is there a way in the 'out-of-container' testing paradigm with openejb for
> the unit test method to control the demarcation of transactions?  
> 
> Here's the use case:
> 1) The unit test is doing entity bean testing, calling various methods on
> the entity facade to test CRUD operations.
> 2) The unit test needs to demarcate transactions so that it can insert,
> delete, then attempt to retrieve deleted entities.  Of course the last
> retrieval should fail because the entity is deleted.  
> 3) But, JPA has the interesting behavior that deleted entities continue to
> be accessible within the deleting transaction.
> 4) Therefore, the unit test needs to demarcate a transaction around the
> delete so that the entity is really removed prior to the last retrieval
> test.
> 
> So, how can one demarcate transactions within a junit test case?
> 
> Thanks,
> 
> Jack
> 
> 

-- 
View this message in context: http://www.nabble.com/Transactions-controlled-by-Unit-Tests-tp15434029p15434676.html
Sent from the OpenEJB User mailing list archive at Nabble.com.