Mockito在verify
方法上的JavaDocs链接到this interesting article关于询问和告知。我在那里特意迷失了“存根互动被隐含地验证”。
我们举一个例子:
想象一下有这个班级
class FooDao {
private EntityManager entityManager;
public FooDao(EntityManager entityManager) {
this.entityManager = entityManager;
}
public List<Foo> findFooByName(String name, String otherParam) {
String hql = "SELECT f FROM Foo f WHERE 1 = 1 ";
if(name != null) {
hql += " AND f.name = :name";
}
if(otherParam != null) {
hql += " AND f.other = :otherParam";
}
TypedQuery<Foo> query = this.entityManager.createQuery(hql, Foo.class);
if(name != null) {
query.setParameter("name", name);
}
if(otherParam != null) {
query.setParameter("otherParam", otherParam);
}
return query.getResultList();
}
}
现在,让我们看看我可以检查这个方法:
首先,我将模拟EntityManager
对象,因为我不想访问真正的数据库。
@InjectMocks
private FooDao dao;
@Mock
private EntityManager entityManager;
现在,我可以添加这样的内容:
@Mock
private TypedQuery<Foo> mockQuery;
@Test
public void testFindFooByName() {
List<Foo> stubData = stubData(); // Method definition omitted for brevity
// Return the custom mockedQuery with the entityManager
Mockito.when(mockQuery.getResultList()).thenReturn(stubData);
Mockito.when(entityManager.createQuery(Mockito.anyString(),
Mockito.eq(Foo.class)))
.thenReturn(mockQuery);
List<Foo> actual = dao.findFooByName("foobar", null);
// Now what should I check?
}
所以,现在问题是要检查什么。我可以添加一个assertEquals(stubData, actual)
,测试就会成功。
我还可以添加:
Mockito.verify(entityManager).createQuery(expectedSql, Foo.class);
Mockito.verify(mockQuery).setParameter("name", "foobar");
第一个验证将确保HQL查询已正确构建,第二个验证将确保参数已正确绑定到查询。这些验证是否必要或只是断言结果是否足够?
答案 0 :(得分:3)
您必须与entityManager
存根交互,否则您的测试会在findFooByName()
调用setParameter()
或getQueryList()
关于是否存根或验证query.getResultList()
电话的选择取决于您希望测试的具体程度......
最不具体
以下测试并非特定于TypedQuery
如何创建,而是满足自己以某种方式创建并调用其getResultList()
方法。
@Test
public void testFindFooByName() {
List<Foo> stubData = stubData();
Mockito.when(entityManager.createQuery(Mockito.anyString(), Mockito.eq(Foo.class))).thenReturn(mockQuery);
dao.findFooByName("foobar", null);
Mockito.verify(mockQuery).getResultList();
}
更具体
以下测试并非特定于TypedQuery
如何创建,而是验证它是以某种方式创建的,并且其getResultList()
调用的结果由方法被测
@Test
public void testFindFooByName() {
List<Foo> stubData = stubData();
Mockito.when(mockQuery.getResultList()).thenReturn(stubData);
Mockito.when(entityManager.createQuery(Mockito.anyString(), Mockito.eq(Foo.class))).thenReturn(mockQuery);
List<Foo> actual = dao.findFooByName("foobar", null);
Assert.assertSame(stubData, actual);
}
最具体
以下测试证明了以下所有内容(来自您的OP):
结果就是我的期望。
参数正确绑定到查询对象。
为给定的参数正确构造HQL查询。
@Test
public void testFindFooByName() {
String name = "foobar";
String otherParam = "otherParam";
String expectedHql = "SELECT f FROM Foo f WHERE 1 = 1 AND f.name = :name AND f.other = :otherParam";
List<Foo> stubData = stubData();
Mockito.when(mockQuery.getResultList()).thenReturn(stubData);
Mockito.when(entityManager.createQuery(Mockito.eq(expectedHql), Mockito.eq(Foo.class))).thenReturn(mockQuery);
List<Foo> actual = dao.findFooByName(name, otherParam);
Assert.assertSame(stubData, actual);
Mockito.verify(mockQuery).setParameter("name", name);
Mockito.verify(mockQuery).setParameter("otherParam", otherParam);
}
因此,总而言之,在确定是否包含验证或存根交互时,您可能还需要考虑: