2015-05-05 25 views
1

我有應該測試以下方法測試方法:取決於Mockito中語句鏈接的空指針異常?

public class SelectionVariantUniqueConstraintValidatorImpl implements UniqueConstraintValidator { 

    private SessionFactory sessionFactory; 

    @Override 
    public List<Criteria> buildValidationCriteria(Object entity, Serializable id, String[] propertyNames) { 
     final SelectionVariant selectionVariant = (SelectionVariant) entity; 
     final Session session = sessionFactory.getCurrentSession(); 
     final Criteria criteria = session.createCriteria(SelectionVariant.class); 

     criteria.add(Restrictions.eq("client", selectionVariant.getClient())); 
     criteria.add(Restrictions.eq("variant.variantName", selectionVariant.getVariant().getVariantName())); 

     return new ArrayList<Criteria>(Arrays.asList(criteria)); 
    } 

    @Required 
    public void setSessionFactory(SessionFactory sessionFactory) { 
     this.sessionFactory = sessionFactory; 
    } 
} 

其運行良好。但是,如果我修改線路如下:

final Criteria criteria = session.createCriteria(SelectionVariant.class).add(Restrictions.eq("client", selectionVariant.getClient())); 
criteria.add(Restrictions.eq("variant.variantName", selectionVariant.getVariant().getVariantName())); 

我會得到:

java.lang.NullPointerException 
    at com.innflow.ebtam.dao.hibernate.variant.SelectionVariantUniqueConstraintValidatorImpl.buildValidationCriteria(SelectionVariantUniqueConstraintValidatorImpl.java:35) 

爲什麼?我錯過了什麼?

這裏是我的測試類:

@RunWith(MockitoJUnitRunner.class) 
public class SelectionVariantUniqueConstraintValidatorImplTest { 

    SelectionVariantUniqueConstraintValidatorImpl selectionVariantUniqueConstraintValidator 
      = new SelectionVariantUniqueConstraintValidatorImpl(); 

    @Mock 
    private SessionFactory sessionFactory; 
    @Mock 
    private Session session; 
    @Mock 
    private Criteria criteria; 

    @Before 
    public void setUp() throws Exception { 
     selectionVariantUniqueConstraintValidator.setSessionFactory(sessionFactory); 
    } 

    @Test 
    public void testBuildValidationCriteria() throws Exception { 
     Mockito.when(sessionFactory.getCurrentSession()).thenReturn(session); 
     Mockito.when(session.createCriteria(SelectionVariant.class)).thenReturn(criteria); 
     SelectionVariant selectionVariant = new SelectionVariant(); 
     Client client = new ClientBuilder().businessKey("HPD").description("desc").version(0).id(1L).build(); 
     selectionVariant.setClient(client); 
     selectionVariantUniqueConstraintValidator.buildValidationCriteria(selectionVariant, null, null); 
     Mockito.verify(criteria,Mockito.atLeastOnce()).add(Restrictions.eq("client", Mockito.any(Client.class))); 
    } 
} 
+1

恕我直言,你應該測試這種代碼針對與集成測試一個真正的數據庫,而不是嘲笑 – artbristol

+0

@artbristol謝謝,是的你是對的,但集成測試是由不同的測試覆蓋。我只是想確保buildValidationCriteria添加所需的限制,僅此而已。你是否仍然認爲這在某種程度上是無用或錯誤的? –

+1

如果你發現兩者都有用,那麼肯定會繼續這樣做。當我得到數據訪問代碼錯誤時,我通常會發現,這是因爲我誤解了數據庫的工作方式,所以直到我使用真正的代碼時才發現它。 – artbristol

回答

2

你嘲笑的Criteriaadd方法。這裏是發生在這裏的事情。在你的第一個版本中,你嘲笑了標準實例。當你調用方法add()它什麼都不做,並且返回null,但它不會打擾你,因爲你不使用返回值。

但是,您在第二個版本中使用的返回值爲add()。爲了讓它工作,你應該:

  1. 化妝的Mockito調用真正add()方法\ ​​
  2. 模擬add()方法,使其恢復原來的標準

例如:

when(criteria.add(any(Restrictions.class))).thenCallRealMethod(); 

when(criteria.add(any(Restrictions.class))).thenReturn(criteria) 

(我不知道它應該是Restrictions.class:它應該是一流的Restrictions.eq()