使用mockito进行DAO层的单元测试

问题描述:

我正在尝试使用Mockito进行Spring + Hibernate项目的单元测试。以下是我的DAO类的实现:使用mockito进行DAO层的单元测试

@Repository 
public class EmployeeDAOImpl implements EmployeeDAO { 
    @Autowired 
    private SessionFactory sessionFactory; 

    public void setSessionFactory(SessionFactory sessionFactory) { 
     this.sessionFactory = sessionFactory; 
     System.out.println("Session factory"); 
    } 
    @Override 
    public ArrayList<Employees> getAllData() { 
     System.out.println("Inside get all data"); 
     Session session = sessionFactory.getCurrentSession(); 
     System.out.println("session created"); 
     Criteria cr = session.createCriteria(Employees.class, "employees").setResultTransformer(
       Criteria.DISTINCT_ROOT_ENTITY); 

     return (ArrayList<Employees>) cr.list(); 
    } 

} 

以下是我的测试类:

public class EmployeeDAOImplTest { 

    @Mock 
    private SessionFactory sessionFactory; 
    @Mock 
    private Session session; 
    @Mock 
    Criteria criteria; 
    @Spy 
    ArrayList<Employees> employees = new ArrayList<Employees>(); 

    private EmployeeDAO dao; 

    @Before 
    public void setUp() throws Exception { 
     MockitoAnnotations.initMocks(this); 
     dao = new EmployeeDAOImpl(); 
     dao.setSessionFactory(sessionFactory); 
     employees = getEmpDetails(); 
     Mockito.doReturn(session).when(sessionFactory).getCurrentSession(); 

    } 

    @Test 
    public void testGetAllData() { 
     Mockito.doReturn(criteria).when(session) 
       .createCriteria(ConceptModelDetails.class); 
     Mockito.doReturn(employees).when(criteria).list(); 
      assertEquals(employees, dao.getAllData()); 
    } 

    private ArrayList<Employees> getEmpDetails() { 
     ArrayList<Employees> array = new ArrayList<Employees>(); 
     Employees emp = new Employees(); 
     emp.setName("xyz"); 
     emp.setId(12); 
     array.add(cm); 
     return array; 
    } 

} 

employees是员工的伪排列列表。请所说的其实是他的问题here.When我运行这个测试时,我得到一个失败与空指针异常的:

Criteria cr = session.createCriteria(Employees.class, "employees").setResultTransformer(
        Criteria.DISTINCT_ROOT_ENTITY); 

堆栈跟踪:

java.lang.NullPointerException 
    at com.assignment.dao.impl.EmployeeDAOImpl.getAllData(EmployeeDAOImpl.java:77) 
    at com.assignment.DAOTest.EmployeeDAOImplTest.testGetAllData(EmployeeDAOImplTest.java:84) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:606) 
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44) 
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) 
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41) 
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) 
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28) 
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76) 
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193) 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42) 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184) 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236) 
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) 
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192) 
+0

始终包含堆栈跟踪。 – chrylis

+0

(就此而言,请考虑使用Spring Data而不是手动编写DAO。) – chrylis

+0

员工为什么是@Spy?为什么你要在声明中实例化它? –

EmployeeDAOImpl包含以下代码:

Criteria cr = session.createCriteria(Employees.class, "employees").setResultTransformer(
      Criteria.DISTINCT_ROOT_ENTITY); 

您的测试有:

Mockito.doReturn(criteria).when(session) 
      .createCriteria(ConceptModelDetails.class); 

您正确地嘲笑了它正在返回的sessionFactorysession,只要我可以从您的代码中知道。但是,您没有正确地嘲笑session.createCriteria(Employee.class, "employees")(而是,您正在设置session.createCriteria(ConceptModelDetails.class)的返回值)。因此,模拟的返回值将是null。因此,当您立即解除引用时(呼叫setResultTransformer),您将获得NullPointerException

为了验证这一点,尝试步入调试器,或添加日志语句EmployeeDAOImpl,即表现出sessionFactorysession的值,然后从session.createCriteria(...)结果。