在 java 测试中没有收到错误
Doesn't receive an error in java test
我的测试不应该通过。我应该在第 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;
}
}
我不明白为什么您会期望 #2 断言失败。您的测试在 454
中通过(作为 Long
)进入 getPersonListByOtdelId()
,因此将被传递到 query.setParameter()
。 #1 中的 when()
代码本质上是空操作,因为没有使用这些值调用 query.setParameter()
,但是如果 when()
中指定的调用从不调用,Mockito 不会抱怨发生了,被测代码不检查 return 值,所以没有例外。
无论如何,你不需要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 不会 return 模拟查询(当然,除非您使用 RETURNS_MOCKS).
综上所述,我认为上述测试不是一个好的测试。测试几乎完全是代码的镜像,它不验证代码是否有效。换句话说,它是一个 change detector test.
我不会使用模拟框架来测试 PersonDaoImpl
。相反,我会编写一个启动内存数据库的测试,使用一个模式文件,该文件也用于在生产中创建实际的 table。
我会使用模拟来测试依赖于 PersonDAO
的 class。
我的测试不应该通过。我应该在第 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;
}
}
我不明白为什么您会期望 #2 断言失败。您的测试在 454
中通过(作为 Long
)进入 getPersonListByOtdelId()
,因此将被传递到 query.setParameter()
。 #1 中的 when()
代码本质上是空操作,因为没有使用这些值调用 query.setParameter()
,但是如果 when()
中指定的调用从不调用,Mockito 不会抱怨发生了,被测代码不检查 return 值,所以没有例外。
无论如何,你不需要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 不会 return 模拟查询(当然,除非您使用 RETURNS_MOCKS).
综上所述,我认为上述测试不是一个好的测试。测试几乎完全是代码的镜像,它不验证代码是否有效。换句话说,它是一个 change detector test.
我不会使用模拟框架来测试 PersonDaoImpl
。相反,我会编写一个启动内存数据库的测试,使用一个模式文件,该文件也用于在生产中创建实际的 table。
我会使用模拟来测试依赖于 PersonDAO
的 class。