2012-01-22 50 views
1

我想用JUnit測試我的Session Beans,但是我不能。我嘗試了很多方法,但仍然有一些例外。 這裏是我需要的:如何使用JUnit與EJB3和JPA

  • 我有幾個無狀態會話bean我需要測試。每個人都有相同的@PersistenceContext和使用EntityManager
  • 與我的測試用例我需要測試他們的方法。例如:如果我添加一個用戶名爲X的用戶,然後嘗試添加另一個用戶名相同的用戶名,我想捕獲一個異常。

有人可以提供一個簡單而簡短的通用測試示例嗎?我已經閱讀了很多,但是我總是遇到一個錯誤(當我調用方法如sessionBean.method()(例如,entityManager.find(...)),或者我無法初始化Context或其他的方法時,我會得到NullPointerExceptionEntityManagerPersistenceException)。

+0

你如何編寫測試用例?你是否使用像Arquillian這樣的集成框架或像OpenEJB這樣的嵌入式EJB容器? –

+0

@PiotrNowicki我試了兩種(使用mockito作爲框架)。我不知道如何設置它們,我需要導入...無論如何,任何方法都可以。 – Simon

+0

我有一個簡單的例子:http://stackoverflow.com/questions/6469751/testing-an-ejb-with-junit/20635285#20635285。看看我的答案。 –

回答

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()得到我所需要的實體,鄰proxy.getEntityList()執行查詢檢索的實體的所有實例。或者我可以添加其他方法,如果我想。

4

你可能在安東尼奧·貢薩爾維斯的最新職位之一感興趣:

WYTIWYR : What You Test Is What You Run

它使用講述測試EJB使用的EntityManager:

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

我正在閱讀它,但我看到他使用了一個模擬的實體管理器並將它注入到它的會話bean(其中存在'@ DataSourceDefinition')。但是,我使用'@ PersistenceContext'和'persistence.xml'描述符。所以,我不知道如何適合他的例子。 – Simon

+0

只有當嵌入式EJB容器和Arquillian都沒有使用時,他纔會模仿EntityManager。在任何其他情況下,他使用由容器注入的實際EntityManager。 –

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 - 標記您的類正在測試 @PersistenceContext - 根據persistence.xml中的配置自動創建您的EntityManager實例 - PersistenceUnit。 @InjectInto - 將em實例注入目標(剪切)

有關更多信息,請參閱this

希望這會有所幫助。

0

我爲此使用了Needle。如果你想嘲笑其他物體,它適用於Mockito和EasyMock。

首先我寫了一個persistencte。XML的測試中(src /測試/資源/ 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一針的配置文件/測試/資源,在那裏你告訴你正在使用什麼樣的模擬提供者。例如。我正在使用Mockito:

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

就是這樣。

相關問題