tomee-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Quintin Beukes <quin...@skywalk.co.za>
Subject Re: Hackety hack: @Test, @LocalClient and @Stateless for simple JPA testing
Date Fri, 02 Oct 2009 20:38:40 GMT
Hey,

What you could do is just us an embedded @Stateless class, or even
just one in the same file. Then you don't have to have duplicated
injections. So the test case will be @LocalClient with an @EJB, and
the @EJB will reference an embedded @Stateless @Local (you should be
able to just add both annotations to the same class IIRC).

Further, when you update to OpenEJB 3.1, have a look at:
https://issues.apache.org/jira/browse/OPENEJB-1078

It's a JUnit runner being developed, though it's only compatible with
eh 3.1.2-SNAPSHOT branch. So when Geronimo 2.2 gets released you'll be
able to use this JUnit runner and OpenEJB 3.1.

The runner is going to be great, because you don't need all the
initialization code, and in the end it will support a whole bunch of
stuff like security and transactions (which you want).

Quintin Beukes



On Fri, Oct 2, 2009 at 7:20 PM, Laird Nelson <ljnelson@gmail.com> wrote:
> This falls under the category of interesting hacks.  It also falls under the
> category of "the goggles...they do nothing!".  But it's Friday.
>
> So I'm unit testing, and wanted to use OpenEJB's ability to run an SLSB in a
> transaction really only for the fact that that SLSB could then use an
> injected, transactional EntityManager without hassle.
>
> That is, really the thing I want to test is my JPA machinery--the mappings,
> the validations, etc.  The easiest way to make this happen is to test an
> insert and retrieval with an EntityManager, and the easiest way to get an
> entity manager is to have one injected into a stateless session bean so you
> don't have to manage all the transactions for yourself.  But I'm in unit
> test mode--I don't really want to create an SLSB and a TestCase for every
> stupid JPA scenario I want to test.  Ideally I would {handwave handwave}
> have a transactional entity manager injected into my test case for me
> somehow but {handwave handwave} run as part of the EJB container {more
> handwaving}.  But my test case is not an EJB.  It is at the moment only a
> @LocalClient.
>
> Well, so, I made my TestCase both a @Stateless and a @LocalClient.  :-)  It
> implements a simple interface that basically defines what methods I want to
> have exposed through the local business interface.  Ideally even this step
> wouldn't be necessary--once you can have an interfaceless SLSB in EJB 3.1,
> you can throw this step out.
>
> I annotate my test methods with @Test (from JUnit).  I inject my @EJB (the
> test case itself!) into...uh...itself.  :-)  I also inject an
> EntityManager.  Unfortunately the EntityManager shows up both "in" the
> test-case-as-EJB and the test-case-as-LocalClient.  I just take care not to
> use it in the test-case-as-LocalClient methods.  There is probably a way in
> @Before to null it out in such a case; I'll do that next.
>
> Anyhow, the net effect is that I can use an injected EntityManager in my
> test case which is effectively wrapped in itself as a SLSB.  That's the part
> that makes my eyes go funny.  Anyhow, it makes in-memory JPA testing pretty
> painless.
>
> The whole thing looks like this (the abstract test case I'm inheriting from
> does the OpenEJB initialization, but not much else; the code below is
> condensed for brevity):
>
> import javax.ejb.*;
> import javax.persistence.*;
> import org.junit.Test;
> import junit.openejb.AbstractOpenEJBTestCase;
> import org.apache.openejb.api.LocalClient;
> import static org.junit.Assert.*;
>
> @Stateless @LocalClient
> public class TestCaseXY extends AbstractOpenEJBTestCase implements
> TestClient {
>
>  @EJB private TestClient tc; // a reference to...um...myself
>  @PersistenceContext private EntityManager em;
>
>  // The JUnit test method.  Don't use the EntityManager here;
>  // I think its behavior would be undefined since your
>  // persistence.xml should be designating a JTA data source,
>  // but you're not in a JTA context here.
>  @Test public final void testXYClient() {
>    assertNotNull(this.tc);
>    this.tc.testXY(); // "Forward" to the "real" test method.
>  }
>
>  // The "real" test method.  Run in a transaction, with EJB security, etc.
>  @Override public void testXY() {
>    assertNotNull(this.em);
>    assertNotNull(this.tc);
>    assertNotSame(this.tc, this);
>    // Actual test code goes here
>  }
>
> }
>
> // Interestingly, this doesn't have to be public so you can put it in the
> same file.
> interface TestClient {
>  public void testXY();
> }
>
> I hope someone finds this useful; feel free to get in touch (ell jay nelson
> at gee mayul dot com) if you have questions.
>
> Best,
> Laird
>

Mime
View raw message