2015-04-06 168 views
1

我越來越NPE而嘲諷的EntityManager,下面是我的代碼,嘲諷的EntityManager

@Stateless 
public class NodeChangeDeltaQueryBean implements NodeChangeDeltaQueryLocal { 

    @PersistenceContext 
    private EntityManager em; 
    @Override 
    public String findIdByNaturalKey(final String replicationDomain, final int sourceNodeIndex, 
            final int nodeChangeNumber) { 
     List<String> result = 
      NodeChangeDelta.findIdByNaturalKey(this.em, replicationDomain, sourceNodeIndex, 
       nodeChangeNumber).getResultList(); 
     return result.isEmpty() ? null : result.get(0); 
    } 
} 

我的實體類

@Entity 
public class NodeChangeDelta implements Serializable, Cloneable, GeneratedEntity, KeyedEntity<String> { 

public static TypedQuery<String> findIdByNaturalKey(final EntityManager em, final String replicationDomain, final int sourceNodeIndex, final int nodeChangeNumber) { 
     return em.createNamedQuery("NodeChangeDelta.findIdByNaturalKey", String.class) 
      .setParameter("replicationDomain", replicationDomain) 
      .setParameter("sourceNodeIndex", sourceNodeIndex) 
      .setParameter("nodeChangeNumber", nodeChangeNumber); 
    } 
} 

我的測試類

@RunWith(MockitoJUnitRunner.class) 
public class NodeChangeDeltaQueryBeanTest { 

    @InjectMocks 
    NodeChangeDeltaQueryBean nodeChangeDeltaQueryBean; 

    @Mock 
    EntityManager em; 

@Test 
    public void testFindIdByNaturalKey() { 
     this.addNodeChangeDelta(); 
     this.nodeChangeDeltaQueryBean.findIdByNaturalKey(this.REPLICATION_DOMAIN, 
      this.SOURCE_NODE_INDEX, this.NODE_CHANGE_NUMDER); 
    } 
} 

在調試EM不null(還有其他參數REPLICATION_DOMAIN, SOURCE_NODE_INDEX,NODE_CHANGE_NUMDER不爲空)在Entit y類,而em.createNamedQuery(「NodeChangeDelta.findIdByNaturalKey」,String.class)爲null。

+0

難道你希望你的模擬執行的實際查詢?這是行不通的。它不知道你的數據源,持久化上下文,命名查詢等。 – 2015-04-06 10:34:05

回答

0

在Mockito中,任何未明確配置的模擬方法調用總是返回null。因此在findIdByNaturalKey,em.createNamedQuery正在返回null等NPE在setParameter。您需要將其配置爲RETURN_MOCKS

此外,我不確定@InjectMocks是否支持@PersistenceContext。如果沒有,則em可能爲空。如果是這樣,請讓我知道,以上是你的問題。

+0

'@InjectMocks'不是spring/jee意識到的,它只是試圖找到一個匹配類型。它不是一個真正的依賴注入框架。 – Brice 2015-04-06 12:21:59

1

在維基的Mockito:Don't mock types you don't own !

這不是一個難行,但越過這條線可能有反響! (很有可能)。

  1. 想象一下嘲笑第三方庫的代碼。在第三個庫的特定升級之後,邏輯可能會改變一點,但測試套件將會執行得很好,因爲它被嘲弄。所以,以後想,一切都很好走,牆壁是綠色的,畢竟軟件部署和... 繁榮
  2. 這可能是一個跡象,目前的設計是不夠脫離這第三黨的圖書館。
  3. 另一個問題是,第三方庫可能很複雜,需要大量的模擬才能正常工作。這會導致過度指定的測試和複雜的裝置,這本身就影響了緊湊且可讀的目標。或者由於模擬外部系統的複雜性,測試不足以覆蓋代碼。

相反,最常見的方法是在外部庫/系統周圍創建包裝,雖然人們應該意識到抽象泄漏的風險,其中太多低級API,概念或例外超出邊界的包裝。爲了驗證與第三方庫的集成,編寫集成測試,並使其儘可能緊湊和可讀。

,你沒有控制模擬類型可以被認爲是(嘲諷)反模式。雖然EntityManager幾乎是標準,但我們不應該認爲即將到來的JDK/JSR版本中不會有任何行爲改變(它已經在API的其他部分發生過無數次了,請看JDK發行說明)。再加上真正的實現可能在他們的行爲中微妙不易被嘲笑,測試可能是綠色的,但生產的雄貓隊着火了(真實的故事)。我的觀點是,如果代碼需要模擬一種我不擁有的類型,那麼設計應該改變asap,所以我,我的同事或這個代碼的未來維護者不會落入這些陷阱。

此外,wiki鏈接到其他博客條目,描述他們試圖模擬他們沒有控制的類型時遇到的問題。

相反,我真的建議大家不要使用模擬當測試與另一個系統的集成。我相信數據庫的東西,Arquillian是要走的東西,該項目似乎相當活躍。


從我的回答改編:https://stackoverflow.com/a/28698223/48136