如何将JUnit与EJB3和JPA一起使用

时间:2012-01-22 21:06:48

标签: unit-testing jpa ejb-3.0 junit4

我正在尝试使用JUnit测试我的会话Bean,但我不能。我尝试了很多方法,但仍然有一些例外。 这就是我需要的:

  • 我需要测试一些无状态会话Bean。每个都有相同的@PersistenceContext并使用EntityManager
  • 在我的测试用例中,我需要测试他们的方法。例如:如果我添加一个用户名为X的用户,然后我尝试添加另一个用户名相同的用户,我想抓住一个例外。

有人可以提供一个简单而简短的通用测试示例吗?我已经阅读了很多内容,但是我总是收到错误(当我调用类似NullPointerException的方法时,EntityManager得到sessionBean.method()(例如entityManager.find(...) }}),或者我无法初始化Context或其他PersistenceException)。

4 个答案:

答案 0 :(得分:4)

您可能对Antonio Goncalves的最新帖子感兴趣:

WYTIWYR : What You Test Is What You Run

它告诉我使用以下方法使用EntityManager测试EJB:

  • Mockito,
  • 嵌入式EJB容器,
  • 的Arquillian。

答案 1 :(得分:1)

我解决了创建Stateless Session Bean并将其Entity Manager注入测试类的问题。我发布代码以防有人需要它:

@Stateless(name = "TestProxy")
@Remote({TestProxyRemote.class})
public class TestProxy implements TestProxyRemote {

    @PersistenceContext(unitName = "mph")
    private EntityManager em;

    @Override
    public void persist(Object o) {
        em.persist(o);
    }

    @Override
    public void clear() {
        em.clear();
    }

    @Override
    public void merge(Object o) {
        em.merge(o);
    }

    @Override
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public Object find(Class classe, String key) {
        return em.find(classe, key);
    }

    @Override
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public Object find(Class classe, long key) {
        return em.find(classe, key);
    }

    @SuppressWarnings("rawtypes")
    @Override
    public List getEntityList(String query) {
        Query q = em.createQuery(query);
        return q.getResultList();
    }

}



public class MyTest {

    @BeforeClass
    public static void setUpBeforeClass() throws NamingException {
        Properties env = new Properties();
        env.setProperty(Context.INITIAL_CONTEXT_FACTORY,"org.jnp.interfaces.NamingContextFactory");
        env.setProperty(Context.PROVIDER_URL, "localhost:1099");
        env.setProperty("java.naming.factory.url.pkgs","org.jboss.naming:org.jnp.interfaces");
        jndiContext = new InitialContext(env);
        try {
            proxy = (TestProxyRemote) jndiContext.lookup("TestProxy/remote");
        } catch (NamingException e) {
            e.printStackTrace();
        }
    }
}

然后我可以使用proxy.find()来获取我需要的实体,o proxy.getEntityList()来执行查询以检索实体的所有实例。或者,如果我愿意,我可以添加其他方法。

答案 2 :(得分:0)

Unitils为JPA提供了非常酷的支持。 Unitils可以与JUnit或TestNG一起使用,如果你需要一个模拟框架,Unitils提供自己的模拟模块以及对EasyMock的支持。

    @JpaEntityManagerFactory(persistenceUnit = "testPersistenceUnit")
    @DataSet(loadStrategy = RefreshLoadStrategy.class)
    public class TimeTrackerTest extends UnitilsTestNG {

        @TestedObject
        private TimeTrackerBean cut = new TimeTrackerBean();

        @InjectInto(target="cut",property="em")
        @PersistenceContext
        private EntityManager em;

        @Test
        @DataSet("TimeTrackerTest.testAddTimeSlot.xml")
        public void yourTest() {
            ...
        }
   }

@JpaEntityManagerFactory - 用于指定持久性单元。它会自动从项目类路径中获取persistence.xml。 @DataSet - 万一你需要加载任何测试数据,你可以使用它。 @TestedObject - 标记您的Class Under Test @PersistenceContext - 从persistence.xml中的配置 - PersistenceUnit自动创建EntityManager实例。 @InjectInto - 将em实例注入目标(剪切)

有关更多信息,请参阅this

希望这有帮助。

答案 3 :(得分:0)

我正在使用Needle。如果你想模仿其他对象,它适用于Mockito和EasyMock。

首先我为测试编写一个persistencte.xml(src / test / resources / META-INF),如下所示:

<persistence-unit name="rapPersistenceTest" transaction-type="RESOURCE_LOCAL">
    <properties>
     <property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
     <property name="javax.persistence.jdbc.url" value="jdbc:h2:~/test"/>
    ...
    </properties>
</persistence-unit>

在我的Junit-Testclass中,我写道:

public class DaoNeedleTest {

//here Needle will create persistenceContext for your testclass
public static DatabaseRule databaseRule = new DatabaseRule("rapPersistenceTest");

//here you can get the entityManager to manipulate data directly
private final EntityManager entityManager = databaseRule.getEntityManager();

@Rule
public NeedleRule needleRule = new NeedleRule(databaseRule);

//here you can instantiate your daoService
@ObjectUnderTest
DAOService daoService;

@Test
public void test() {
    //if your method needs a transaction here you can get it
    entityManager.getTransaction().begin();

    daoService.yourMethod();        

    entityManager.getTransaction().commit();
}

您还需要src / test / resources中的Needle-configuration文件,您可以在其中告诉您正在使用哪种Mock-provider。例如。我正在使用Mockito:

mock.provider=de.akquinet.jbosscc.needle.mock.MockitoProvider

就是这样。