You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomee.apache.org by Laird Nelson <lj...@gmail.com> on 2009/10/02 19:20:56 UTC

Hackety hack: @Test, @LocalClient and @Stateless for simple JPA testing

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

Re: Hackety hack: @Test, @LocalClient and @Stateless for simple JPA testing

Posted by Quintin Beukes <qu...@skywalk.co.za>.
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 <lj...@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
>

Re: Hackety hack: @Test, @LocalClient and @Stateless for simple JPA testing

Posted by Quintin Beukes <qu...@skywalk.co.za>.
I see what you mean with the transaction. If I inject the
EntityManager into a LocalClient without the EJB, it throws a
TransactionRequiredException. Hmm.

Let me see what can be done for this.

Quintin Beukes



On Sat, Oct 3, 2009 at 7:31 PM, Laird Nelson <lj...@gmail.com> wrote:
> Sure:
>
> <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
>
> And:
>
>    properties.setProperty(Context.INITIAL_CONTEXT_FACTORY,
> LocalInitialContextFactory.class.getName());
>    // See
> http://blog.jonasbandi.net/2009/06/restarting-embedded-openejb-container.html
> :
>    properties.setProperty("openejb.embedded.initialcontext.close",
> "destroy");
>
> To create the database:
>
> The database name is: jdbc:h2:mem:test;DB_CLOSE_DELAY=-1 (close delay -1
> means that the db won't shut down until the VM does.  If you set it to 0, it
> shuts down the moment there are no more connections to it.  My problem is I
> don't know how to influence OpenEJB's underlying connection pool such that
> (a) I can guarantee exactly one connection will be open to H2 while the
> LocalInitialContext is up and (b) I can guarantee that when the context is
> closed, so is the connection pool.)
>
> So the properties look like this:
>
>      final String name = "test";
>      properties.setProperty(name, "new://Resource?type=DataSource"); //
> create a data source named "test"
>      properties.setProperty(name + ".JdbcUrl",
> "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1");
>      properties.setProperty(name + ".JdbcDriver", "org.h2.Driver");
>      properties.setProperty(name + ".Username", "sa");
>      properties.setProperty(name + ".Password", "");
>
> Hope that helps.
>
> Best,
> Laird
>
> On Sat, Oct 3, 2009 at 1:20 PM, Quintin Beukes <qu...@skywalk.co.za>wrote:
>
>> Basically, all I want to know is your PersistenceProvider class, your
>> data resource InitialContext configuration for the test, and how you
>> create the database in H2.
>>
>> I got the H2 server running, but went to go shower, so haven't done
>> anything beyond that.
>>
>> Quintin Beukes
>>
>>
>>
>> On Sat, Oct 3, 2009 at 6:55 PM, Laird Nelson <lj...@gmail.com> wrote:
>> > I'll try to put it together; it's spread out over a large project base at
>> > the moment.
>> >
>> > Cheers,
>> > Laird
>> >
>> > On Sat, Oct 3, 2009 at 12:47 PM, Quintin Beukes <quintin@skywalk.co.za
>> >wrote:
>> >
>> >> Hey,
>> >>
>> >> This sounds interesting. Actually a nice way to do tests from a clean
>> >> db, a problem I have myself which I circumvented with a modified
>> >> Hibernate.
>> >>
>> >> Can you send me your H2 OpenEJB configuration. I want to set it up and
>> >> see if I can get it going. Will let you know what I come up with -
>> >> even if it means to make a simple junit runner just for this purpose.
>> >> It would be great to have tests run on a clean db everytime.
>> >>
>> >> Quintin Beukes
>> >>
>> >>
>> >>
>> >> On Sat, Oct 3, 2009 at 6:42 PM, Laird Nelson <lj...@gmail.com>
>> wrote:
>> >> > On Sat, Oct 3, 2009 at 12:07 PM, Quintin Beukes <
>> quintin@skywalk.co.za
>> >> >wrote:
>> >> >
>> >> >> Yes,it is managed by the container and the context. The initial
>> >> >> context will close with the VM. Afaik it will have the same behaviour
>> >> >> after the test closes as the EJB would.
>> >> >
>> >> >
>> >> > OK; good to know.
>> >> >
>> >> > From you e-mail I figure your focus is on the automatic destruction of
>> >> >>
>> >> > the db.
>> >> >
>> >> >
>> >> > Yes.  H2, specifically.
>> >> >
>> >> > I've *never* had luck with the DB being automatically destroyed
>> between
>> >> > tests.  I've closed the context, used the magic property
>> (destroyOnClose?
>> >> > don't remember offhand), tried setting up H2 without the
>> DB_CLOSE_DELAY
>> >> > setting, *with* the DB_CLOSE_DELAY setting--nothing.  It might have to
>> do
>> >> > with the strange intersection of (a) there being a connection pool and
>> >> (b)
>> >> > H2's being an in-memory database that tries to destroy itself when it
>> >> thinks
>> >> > it's safe to do so.
>> >> >
>> >> > I can verify this because when I have two test methods that each try
>> to
>> >> > persist an object with the same ID--which would succeed in a blank
>> >> > database--my second method fails.
>> >> >
>> >> > To be clear, then, I want my named H2 database to be wiped out and
>> >> > recreated--complete with DDL generation as described by my JPA
>> >> > mappings--before each test method is run.
>> >> >
>> >> > To put it one final way, I want my test code to look like this:
>> >> > X x = new X();
>> >> > this.em.persist(x);
>> >> >
>> >> > ...i.e. no beginning transactions, no shutting down databases, no
>> mucking
>> >> > about with EntityManagerFactories, etc. etc. etc.  Just bare bones
>> >> > simplicity.  Frankly OpenEJB need not even be involved, but it seemed
>> >> like
>> >> > an easy black box that would enable most of these kinds of tests.
>> >> >
>> >> > Thanks for getting involved,
>> >> > Laird
>> >> >
>> >>
>> >
>>
>

Re: Hackety hack: @Test, @LocalClient and @Stateless for simple JPA testing

Posted by Laird Nelson <lj...@gmail.com>.
Sure:

<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>

And:

    properties.setProperty(Context.INITIAL_CONTEXT_FACTORY,
LocalInitialContextFactory.class.getName());
    // See
http://blog.jonasbandi.net/2009/06/restarting-embedded-openejb-container.html
:
    properties.setProperty("openejb.embedded.initialcontext.close",
"destroy");

To create the database:

The database name is: jdbc:h2:mem:test;DB_CLOSE_DELAY=-1 (close delay -1
means that the db won't shut down until the VM does.  If you set it to 0, it
shuts down the moment there are no more connections to it.  My problem is I
don't know how to influence OpenEJB's underlying connection pool such that
(a) I can guarantee exactly one connection will be open to H2 while the
LocalInitialContext is up and (b) I can guarantee that when the context is
closed, so is the connection pool.)

So the properties look like this:

      final String name = "test";
      properties.setProperty(name, "new://Resource?type=DataSource"); //
create a data source named "test"
      properties.setProperty(name + ".JdbcUrl",
"jdbc:h2:mem:test;DB_CLOSE_DELAY=-1");
      properties.setProperty(name + ".JdbcDriver", "org.h2.Driver");
      properties.setProperty(name + ".Username", "sa");
      properties.setProperty(name + ".Password", "");

Hope that helps.

Best,
Laird

On Sat, Oct 3, 2009 at 1:20 PM, Quintin Beukes <qu...@skywalk.co.za>wrote:

> Basically, all I want to know is your PersistenceProvider class, your
> data resource InitialContext configuration for the test, and how you
> create the database in H2.
>
> I got the H2 server running, but went to go shower, so haven't done
> anything beyond that.
>
> Quintin Beukes
>
>
>
> On Sat, Oct 3, 2009 at 6:55 PM, Laird Nelson <lj...@gmail.com> wrote:
> > I'll try to put it together; it's spread out over a large project base at
> > the moment.
> >
> > Cheers,
> > Laird
> >
> > On Sat, Oct 3, 2009 at 12:47 PM, Quintin Beukes <quintin@skywalk.co.za
> >wrote:
> >
> >> Hey,
> >>
> >> This sounds interesting. Actually a nice way to do tests from a clean
> >> db, a problem I have myself which I circumvented with a modified
> >> Hibernate.
> >>
> >> Can you send me your H2 OpenEJB configuration. I want to set it up and
> >> see if I can get it going. Will let you know what I come up with -
> >> even if it means to make a simple junit runner just for this purpose.
> >> It would be great to have tests run on a clean db everytime.
> >>
> >> Quintin Beukes
> >>
> >>
> >>
> >> On Sat, Oct 3, 2009 at 6:42 PM, Laird Nelson <lj...@gmail.com>
> wrote:
> >> > On Sat, Oct 3, 2009 at 12:07 PM, Quintin Beukes <
> quintin@skywalk.co.za
> >> >wrote:
> >> >
> >> >> Yes,it is managed by the container and the context. The initial
> >> >> context will close with the VM. Afaik it will have the same behaviour
> >> >> after the test closes as the EJB would.
> >> >
> >> >
> >> > OK; good to know.
> >> >
> >> > From you e-mail I figure your focus is on the automatic destruction of
> >> >>
> >> > the db.
> >> >
> >> >
> >> > Yes.  H2, specifically.
> >> >
> >> > I've *never* had luck with the DB being automatically destroyed
> between
> >> > tests.  I've closed the context, used the magic property
> (destroyOnClose?
> >> > don't remember offhand), tried setting up H2 without the
> DB_CLOSE_DELAY
> >> > setting, *with* the DB_CLOSE_DELAY setting--nothing.  It might have to
> do
> >> > with the strange intersection of (a) there being a connection pool and
> >> (b)
> >> > H2's being an in-memory database that tries to destroy itself when it
> >> thinks
> >> > it's safe to do so.
> >> >
> >> > I can verify this because when I have two test methods that each try
> to
> >> > persist an object with the same ID--which would succeed in a blank
> >> > database--my second method fails.
> >> >
> >> > To be clear, then, I want my named H2 database to be wiped out and
> >> > recreated--complete with DDL generation as described by my JPA
> >> > mappings--before each test method is run.
> >> >
> >> > To put it one final way, I want my test code to look like this:
> >> > X x = new X();
> >> > this.em.persist(x);
> >> >
> >> > ...i.e. no beginning transactions, no shutting down databases, no
> mucking
> >> > about with EntityManagerFactories, etc. etc. etc.  Just bare bones
> >> > simplicity.  Frankly OpenEJB need not even be involved, but it seemed
> >> like
> >> > an easy black box that would enable most of these kinds of tests.
> >> >
> >> > Thanks for getting involved,
> >> > Laird
> >> >
> >>
> >
>

Re: Hackety hack: @Test, @LocalClient and @Stateless for simple JPA testing

Posted by Quintin Beukes <qu...@skywalk.co.za>.
Basically, all I want to know is your PersistenceProvider class, your
data resource InitialContext configuration for the test, and how you
create the database in H2.

I got the H2 server running, but went to go shower, so haven't done
anything beyond that.

Quintin Beukes



On Sat, Oct 3, 2009 at 6:55 PM, Laird Nelson <lj...@gmail.com> wrote:
> I'll try to put it together; it's spread out over a large project base at
> the moment.
>
> Cheers,
> Laird
>
> On Sat, Oct 3, 2009 at 12:47 PM, Quintin Beukes <qu...@skywalk.co.za>wrote:
>
>> Hey,
>>
>> This sounds interesting. Actually a nice way to do tests from a clean
>> db, a problem I have myself which I circumvented with a modified
>> Hibernate.
>>
>> Can you send me your H2 OpenEJB configuration. I want to set it up and
>> see if I can get it going. Will let you know what I come up with -
>> even if it means to make a simple junit runner just for this purpose.
>> It would be great to have tests run on a clean db everytime.
>>
>> Quintin Beukes
>>
>>
>>
>> On Sat, Oct 3, 2009 at 6:42 PM, Laird Nelson <lj...@gmail.com> wrote:
>> > On Sat, Oct 3, 2009 at 12:07 PM, Quintin Beukes <quintin@skywalk.co.za
>> >wrote:
>> >
>> >> Yes,it is managed by the container and the context. The initial
>> >> context will close with the VM. Afaik it will have the same behaviour
>> >> after the test closes as the EJB would.
>> >
>> >
>> > OK; good to know.
>> >
>> > From you e-mail I figure your focus is on the automatic destruction of
>> >>
>> > the db.
>> >
>> >
>> > Yes.  H2, specifically.
>> >
>> > I've *never* had luck with the DB being automatically destroyed between
>> > tests.  I've closed the context, used the magic property (destroyOnClose?
>> > don't remember offhand), tried setting up H2 without the DB_CLOSE_DELAY
>> > setting, *with* the DB_CLOSE_DELAY setting--nothing.  It might have to do
>> > with the strange intersection of (a) there being a connection pool and
>> (b)
>> > H2's being an in-memory database that tries to destroy itself when it
>> thinks
>> > it's safe to do so.
>> >
>> > I can verify this because when I have two test methods that each try to
>> > persist an object with the same ID--which would succeed in a blank
>> > database--my second method fails.
>> >
>> > To be clear, then, I want my named H2 database to be wiped out and
>> > recreated--complete with DDL generation as described by my JPA
>> > mappings--before each test method is run.
>> >
>> > To put it one final way, I want my test code to look like this:
>> > X x = new X();
>> > this.em.persist(x);
>> >
>> > ...i.e. no beginning transactions, no shutting down databases, no mucking
>> > about with EntityManagerFactories, etc. etc. etc.  Just bare bones
>> > simplicity.  Frankly OpenEJB need not even be involved, but it seemed
>> like
>> > an easy black box that would enable most of these kinds of tests.
>> >
>> > Thanks for getting involved,
>> > Laird
>> >
>>
>

Re: Hackety hack: @Test, @LocalClient and @Stateless for simple JPA testing

Posted by Laird Nelson <lj...@gmail.com>.
I'll try to put it together; it's spread out over a large project base at
the moment.

Cheers,
Laird

On Sat, Oct 3, 2009 at 12:47 PM, Quintin Beukes <qu...@skywalk.co.za>wrote:

> Hey,
>
> This sounds interesting. Actually a nice way to do tests from a clean
> db, a problem I have myself which I circumvented with a modified
> Hibernate.
>
> Can you send me your H2 OpenEJB configuration. I want to set it up and
> see if I can get it going. Will let you know what I come up with -
> even if it means to make a simple junit runner just for this purpose.
> It would be great to have tests run on a clean db everytime.
>
> Quintin Beukes
>
>
>
> On Sat, Oct 3, 2009 at 6:42 PM, Laird Nelson <lj...@gmail.com> wrote:
> > On Sat, Oct 3, 2009 at 12:07 PM, Quintin Beukes <quintin@skywalk.co.za
> >wrote:
> >
> >> Yes,it is managed by the container and the context. The initial
> >> context will close with the VM. Afaik it will have the same behaviour
> >> after the test closes as the EJB would.
> >
> >
> > OK; good to know.
> >
> > From you e-mail I figure your focus is on the automatic destruction of
> >>
> > the db.
> >
> >
> > Yes.  H2, specifically.
> >
> > I've *never* had luck with the DB being automatically destroyed between
> > tests.  I've closed the context, used the magic property (destroyOnClose?
> > don't remember offhand), tried setting up H2 without the DB_CLOSE_DELAY
> > setting, *with* the DB_CLOSE_DELAY setting--nothing.  It might have to do
> > with the strange intersection of (a) there being a connection pool and
> (b)
> > H2's being an in-memory database that tries to destroy itself when it
> thinks
> > it's safe to do so.
> >
> > I can verify this because when I have two test methods that each try to
> > persist an object with the same ID--which would succeed in a blank
> > database--my second method fails.
> >
> > To be clear, then, I want my named H2 database to be wiped out and
> > recreated--complete with DDL generation as described by my JPA
> > mappings--before each test method is run.
> >
> > To put it one final way, I want my test code to look like this:
> > X x = new X();
> > this.em.persist(x);
> >
> > ...i.e. no beginning transactions, no shutting down databases, no mucking
> > about with EntityManagerFactories, etc. etc. etc.  Just bare bones
> > simplicity.  Frankly OpenEJB need not even be involved, but it seemed
> like
> > an easy black box that would enable most of these kinds of tests.
> >
> > Thanks for getting involved,
> > Laird
> >
>

Re: Hackety hack: @Test, @LocalClient and @Stateless for simple JPA testing

Posted by Quintin Beukes <qu...@skywalk.co.za>.
Hey,

This sounds interesting. Actually a nice way to do tests from a clean
db, a problem I have myself which I circumvented with a modified
Hibernate.

Can you send me your H2 OpenEJB configuration. I want to set it up and
see if I can get it going. Will let you know what I come up with -
even if it means to make a simple junit runner just for this purpose.
It would be great to have tests run on a clean db everytime.

Quintin Beukes



On Sat, Oct 3, 2009 at 6:42 PM, Laird Nelson <lj...@gmail.com> wrote:
> On Sat, Oct 3, 2009 at 12:07 PM, Quintin Beukes <qu...@skywalk.co.za>wrote:
>
>> Yes,it is managed by the container and the context. The initial
>> context will close with the VM. Afaik it will have the same behaviour
>> after the test closes as the EJB would.
>
>
> OK; good to know.
>
> From you e-mail I figure your focus is on the automatic destruction of
>>
> the db.
>
>
> Yes.  H2, specifically.
>
> I've *never* had luck with the DB being automatically destroyed between
> tests.  I've closed the context, used the magic property (destroyOnClose?
> don't remember offhand), tried setting up H2 without the DB_CLOSE_DELAY
> setting, *with* the DB_CLOSE_DELAY setting--nothing.  It might have to do
> with the strange intersection of (a) there being a connection pool and (b)
> H2's being an in-memory database that tries to destroy itself when it thinks
> it's safe to do so.
>
> I can verify this because when I have two test methods that each try to
> persist an object with the same ID--which would succeed in a blank
> database--my second method fails.
>
> To be clear, then, I want my named H2 database to be wiped out and
> recreated--complete with DDL generation as described by my JPA
> mappings--before each test method is run.
>
> To put it one final way, I want my test code to look like this:
> X x = new X();
> this.em.persist(x);
>
> ...i.e. no beginning transactions, no shutting down databases, no mucking
> about with EntityManagerFactories, etc. etc. etc.  Just bare bones
> simplicity.  Frankly OpenEJB need not even be involved, but it seemed like
> an easy black box that would enable most of these kinds of tests.
>
> Thanks for getting involved,
> Laird
>

Re: Hackety hack: @Test, @LocalClient and @Stateless for simple JPA testing

Posted by Laird Nelson <lj...@gmail.com>.
On Sat, Oct 3, 2009 at 12:07 PM, Quintin Beukes <qu...@skywalk.co.za>wrote:

> Yes,it is managed by the container and the context. The initial
> context will close with the VM. Afaik it will have the same behaviour
> after the test closes as the EJB would.


OK; good to know.

>From you e-mail I figure your focus is on the automatic destruction of
>
the db.


Yes.  H2, specifically.

I've *never* had luck with the DB being automatically destroyed between
tests.  I've closed the context, used the magic property (destroyOnClose?
don't remember offhand), tried setting up H2 without the DB_CLOSE_DELAY
setting, *with* the DB_CLOSE_DELAY setting--nothing.  It might have to do
with the strange intersection of (a) there being a connection pool and (b)
H2's being an in-memory database that tries to destroy itself when it thinks
it's safe to do so.

I can verify this because when I have two test methods that each try to
persist an object with the same ID--which would succeed in a blank
database--my second method fails.

To be clear, then, I want my named H2 database to be wiped out and
recreated--complete with DDL generation as described by my JPA
mappings--before each test method is run.

To put it one final way, I want my test code to look like this:
X x = new X();
this.em.persist(x);

...i.e. no beginning transactions, no shutting down databases, no mucking
about with EntityManagerFactories, etc. etc. etc.  Just bare bones
simplicity.  Frankly OpenEJB need not even be involved, but it seemed like
an easy black box that would enable most of these kinds of tests.

Thanks for getting involved,
Laird

Re: Hackety hack: @Test, @LocalClient and @Stateless for simple JPA testing

Posted by Quintin Beukes <qu...@skywalk.co.za>.
Yes,it is managed by the container and the context. The initial
context will close with the VM. Afaik it will have the same behaviour
after the test closes as the EJB would. Though because your test isn't
created and it's instance managed by the container, the transactions
won't happen "before" and "after" the test automatically. That's
something that's going to be in the JUnit-runner.

Anyway, why do you need this behavior for tests?

>From you e-mail I figure your focus is on the automatic destruction of
the db. This should do it for you. I don't see how CMT could be the
reason for that happening. EJB closing down maybe, but not a single
CMT. And OpenEJB closes down even if you don't have EJBs, once the VM
closes down, and this behavior is the same whether or not you have
EJBs, as long as you start it in the first place, which happens with
the InitialContext.

Best thing is to try it and see if it works, then if it doesn't - come
back and we'll see if there is some way to do it. OpenEJB is very
flexible, which is one of the things that makes it brilliant.

Quintin Beukes



On Sat, Oct 3, 2009 at 4:55 PM, Laird Nelson <lj...@gmail.com> wrote:
> On Fri, Oct 2, 2009 at 4:42 PM, Quintin Beukes <qu...@skywalk.co.za>wrote:
>
>> If you really only want to test the JPA entities, and don't mind the
>> transactions, why not remove the @Stateless and @EJB completely, and
>> just make your test @LocalClient and inject an entity manager?
>>
>
> That may be just the ticket.  I wanted to avoid all the boilerplate of
> creating and committing transactions.  If I inject an EntityManager into my
> LocalClient, is it managed by the container?  Or does it behave in a more
> Java SE manner?  Does it start and automatically commit the transaction?
>
> Mainly I'm looking to do whatever is simplest to get the
> auto-context-closing behavior of the local InitialContext, because that
> wipes out my in-memory H2 database automatically between tests.  I wanted to
> combine that behavior with automatic transaction management to eliminate
> EntityManager boilerplate operations.  Whatever is the simplest way to do
> this involving the least code--I'm all ears.
>
> Best,
> Laird
>

Re: Hackety hack: @Test, @LocalClient and @Stateless for simple JPA testing

Posted by Laird Nelson <lj...@gmail.com>.
On Fri, Oct 2, 2009 at 4:42 PM, Quintin Beukes <qu...@skywalk.co.za>wrote:

> If you really only want to test the JPA entities, and don't mind the
> transactions, why not remove the @Stateless and @EJB completely, and
> just make your test @LocalClient and inject an entity manager?
>

That may be just the ticket.  I wanted to avoid all the boilerplate of
creating and committing transactions.  If I inject an EntityManager into my
LocalClient, is it managed by the container?  Or does it behave in a more
Java SE manner?  Does it start and automatically commit the transaction?

Mainly I'm looking to do whatever is simplest to get the
auto-context-closing behavior of the local InitialContext, because that
wipes out my in-memory H2 database automatically between tests.  I wanted to
combine that behavior with automatic transaction management to eliminate
EntityManager boilerplate operations.  Whatever is the simplest way to do
this involving the least code--I'm all ears.

Best,
Laird

Re: Hackety hack: @Test, @LocalClient and @Stateless for simple JPA testing

Posted by Quintin Beukes <qu...@skywalk.co.za>.
Just a note - something I learned from painfully.

This is regarding JTA transactions and unit testing.

If you do your unit tests, try and use the EJBs your testing close as
possible as to how you would really call them. If you're making
separate EJB calls from OUTSIDE a JTA transaction, you should also
unit test these calls separately. If you wrap them inside a
transaction while unit testing, but they're not in production (or the
other way around), you might start noticing the one working and the
other failing with errors. This is especially noticeable when more
than one transaction is in the loop (like with multiple persistence
units).

Just thought I'd mention this, before you start digging through weird
hard to explain errors.

Quintin Beukes



On Fri, Oct 2, 2009 at 10:42 PM, Quintin Beukes <qu...@skywalk.co.za> wrote:
> If you really only want to test the JPA entities, and don't mind the
> transactions, why not remove the @Stateless and @EJB completely, and
> just make your test @LocalClient and inject an entity manager?
>
> If this is not the case, why exactly do you need the JTA? In this case
> just split up the test case and the EJB. That double injections of the
> entity manager and EJB seems ugly.
>
> Quintin Beukes
>
>
>
> On Fri, Oct 2, 2009 at 7:20 PM, Laird Nelson <lj...@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
>>
>

Re: Hackety hack: @Test, @LocalClient and @Stateless for simple JPA testing

Posted by Quintin Beukes <qu...@skywalk.co.za>.
If you really only want to test the JPA entities, and don't mind the
transactions, why not remove the @Stateless and @EJB completely, and
just make your test @LocalClient and inject an entity manager?

If this is not the case, why exactly do you need the JTA? In this case
just split up the test case and the EJB. That double injections of the
entity manager and EJB seems ugly.

Quintin Beukes



On Fri, Oct 2, 2009 at 7:20 PM, Laird Nelson <lj...@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
>