[2.0.4] FunctionalTest error "No EntityManager bound to this thread"

1,242 views
Skip to first unread message

Ian Downard

unread,
Oct 5, 2012, 3:22:23 PM10/5/12
to play-fr...@googlegroups.com
I'm trying to write a functional test to directly exercise the save method of a JPA entity without going through a Controller.  Is this possible?  When I run "play test", I get error, "No EntityManager bound to this thread. Try to annotate your action method with @play.db.jpa.Transactional".

My functional test method is defined as follows:

    @Test
    @play.db.jpa.Transactional
    public void persistNewScenario() {
        Scenario testscenario = new Scenario();
        testscenario.name = "test scenario";
        testscenario.save();
        }


My JPA entity class is defined as follows:

@Entity
@SequenceGenerator(name = "scenario_seq", sequenceName = "scenario_seq")
public class Scenario {
    public Long id;
    public String name;

    public void save() {
        this.id = id;
        JPA.em().persist(this);
    }


Thanks for any help.

--Ian

James Roper

unread,
Oct 7, 2012, 9:06:16 PM10/7/12
to play-fr...@googlegroups.com
Two options:

@Test
public void someTest {
    JPA.withTransaction(new Function0<Void>() {
        public Void apply() {
            // Test code here
            return null;
        }
    });
}

or

private EntityManager em;

@Before
public void setUp() {
    EntityManager em = JPA.em(name);
    JPA.bindForCurrentThread(em);
}

@After
public void tearDown() {
    JPA.bindForCurrentThread(null);
    em.close();
}

You may want to extract this into a separate class that your other JPA tests inherit from.

Ben L

unread,
Jan 19, 2013, 9:00:45 PM1/19/13
to play-fr...@googlegroups.com
Hey James,

I couldn't get your code to work - I kept getting a null em.  I made a couple of tweeks by following through how the Helpers class worked to get the following which works for me.  Using jUnit with Play and JPA has been far too hard... hopefully this will make it a bit easier.

import javax.persistence.EntityManager;

import models.account.User;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import play.db.jpa.JPA;
import play.db.jpa.JPAPlugin;
import play.test.FakeApplication;
import play.test.Helpers;
import scala.Option;

public class TestStuff {

private EntityManager em;
@Before
public void setUp() {
FakeApplication app = Helpers.fakeApplication();
Helpers.start(app);
Option<JPAPlugin> jpaPlugin = app.getWrappedApplication().plugin(JPAPlugin.class);
em = jpaPlugin.get().em("default");
   JPA.bindForCurrentThread(em);
}

@After
public void tearDown() {
   JPA.bindForCurrentThread(null);
   em.close();
        }
        @Test
        public void simpleCheck() {
            User user = User.find(1l);
            System.out.println(user.getEmail());

        }
}

Ben L

unread,
Jan 19, 2013, 9:03:48 PM1/19/13
to play-fr...@googlegroups.com
Just converted my Test to extend this AbscractClass to make sure everything is wrapped in a JPA transaction:

package test;

 


 

import javax.persistence.EntityManager;


 

import org.junit.After;

import org.junit.Before;


 

import play.db.jpa.JPA;

import play.db.jpa.JPAPlugin;

import play.test.FakeApplication;

import play.test.Helpers;

import scala.Option;


 

public abstract class AbstractTest {

 

 
protected EntityManager em;

 

 
@Before

 
public void setUp() {

 
FakeApplication app = Helpers.fakeApplication();

 
Helpers.start(app);

 
Option<JPAPlugin> jpaPlugin = app.getWrappedApplication().plugin(JPAPlugin.class);

 em
= jpaPlugin.get().em("default");

     JPA
.bindForCurrentThread(em);

 
}


 

 
@After

 
public void tearDown() {

     JPA
.bindForCurrentThread(null);

     em
.close();

 
}

}


Reply all
Reply to author
Forward
0 new messages