在java测试中没有收到错误

时间:2015-04-03 08:12:41

标签: java testing junit mocking mockito

我的测试不应该通过。我应该在第2行收到错误,因为我在第1行放了一个错误的值new Long(0)。 请告诉我我的错误在哪里。 感谢。

    @Test
    public void getPersonListByOtdelIdTest() {            
        Long otdelId = new Long(454);
        ArgumentCaptor<Long> argumentOtdelId = ArgumentCaptor.forClass(Long.class);
        SessionFactory mockedSessionFactory = mock(SessionFactory.class);
        Session session = mock(Session.class);
        Query query = mock(Query.class);
        PersonDAOImpl personDAO = new PersonDAOImpl(mockedSessionFactory);
        when(mockedSessionFactory.getCurrentSession()). thenReturn(session);
        when(session.createQuery("FROM Person P where P.otdel.otdelId = :otdelId")).thenReturn(query);
 #1-->  when(query.setParameter("otdelId", new Long(0))).thenReturn(query);
        when(query.list()).thenReturn(persons);

        List<Person> expectedPersons =  personDAO.getPersonListByOtdelId(otdelId);

        verify(mockedSessionFactory).getCurrentSession();
        verify(session).createQuery("FROM Person P where P.otdel.otdelId = :otdelId");
        verify(query).setParameter(eq("otdelId"), argumentOtdelId.capture());
        verify(query).list();
 #2-->  assertEquals(otdelId, argumentOtdelId.getValue());
        assertTrue(expectedPersons.containsAll(persons));
    }

 public class PersonDAOImpl implements PersonDAO {
    public List<Person> getPersonListByOtdelId(Long otdelId) {
        Query query = sessionFactory.getCurrentSession().createQuery("FROM Person P where P.otdel.otdelId = :otdelId");
        query.setParameter("otdelId", otdelId);
        List<Person> listPersons = query.list();
        return listPersons;
    } 
 }

1 个答案:

答案 0 :(得分:2)

我不明白为什么你会期望#2的断言失败。您的测试已在454(作为Long)传递到getPersonListByOtdelId(),因此会传递给query.setParameter()。 #1中的when()代码基本上是无操作,因为query.setParameter()没有使用这些值调用,但如果when()中指定的调用从不,则Mockito不会抱怨发生了,被测试的代码没有检查返回值,因此没有例外。

无论如何,您不需要ArgumentCaptor;您只需要让Mockito验证是否已将正确的值传递给setParameter()

事实上,您不需要执行许多验证调用:

@Test
public void getPersonListByOtdelIdTest() {
  Long otdelId = 454L; // or = Long.valueOf(454); don't use new Long
  SessionFactory mockedSessionFactory = mock(SessionFactory.class);
  Session session = mock(Session.class);
  Query query = mock(Query.class);

  when(mockedSessionFactory.getCurrentSession()).thenReturn(session);
  when(session.createQuery("FROM Person P where P.otdel.otdelId = :otdelId"))
      .thenReturn(query);
  when(query.setParameter("otdelId", otdelId)).thenReturn(query);
  when(query.list()).thenReturn(persons);

  PersonDAOImpl personDAO = new PersonDAOImpl(mockedSessionFactory);
  List<Person> result = personDAO.getPersonListByOtdelId(otdelId);

  verify(query).setParameter("otdelId", otdelId);
  assertEquals(result, persons);
}

您无需验证是否已调用getCurrentSession(),因为如果不是正在测试的代码将无法获得会话。您无需验证是否已将正确的查询传递给createQuery(),因为测试中的代码使用了不同的查询,Mockito不会返回模拟查询(当然,除非您使用{{3 }})。

所有人都说,我不认为上述测试是一个很好的测试。测试几乎完全反映了代码,并没有验证代码是否有效。换句话说,它是RETURNS_MOCKS

我不会使用模拟框架来测试PersonDaoImpl。相反,我会编写一个测试来启动一个内存数据库,使用一个模式文件,该文件也用于在生产中创建实际的表。

我会使用模拟来测试依赖于PersonDAO的类。