Java Mockito验证交互与验证结果
Mockito在Java Mockito验证交互与验证结果,java,unit-testing,mockito,Java,Unit Testing,Mockito,Mockito在verify方法上的JavaDocs链接到关于询问和告知。我有点迷茫,特别是“存根交互是隐式验证的” 让我们举一个例子: 想象一个学生上这门课 class FooDao { private EntityManager entityManager; public FooDao(EntityManager entityManager) { this.entityManager = entityManager; } public Li
verify
方法上的JavaDocs链接到关于询问和告知。我有点迷茫,特别是“存根交互是隐式验证的”
让我们举一个例子:
想象一个学生上这门课
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();
}
}
现在,我可以添加如下内容:
@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?
}
第一次验证将确保HQL查询已正确构造,第二次验证将确保参数已正确绑定到查询。这些验证是必需的还是仅仅断言结果就足够了?您必须存根与
entityManager
的交互,否则当FindFoodByName()
调用setParameter()
或getQueryList()时,您的测试将导致NPE被抛出
关于是存根还是验证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();
}
最具体的
以下测试证明了以下所有内容(来自您的OP):
结果正是我所期望的
参数是否正确绑定到查询对象
为给定的参数正确构造HQL查询
@测试
public void testFindFooByName(){
String name=“foobar”;
字符串otherParam=“otherParam”;
String expectedHql=“从Foo f中选择f,其中1=1,f.name=:name,f.other=:otherParam”;
List stubData=stubData();
Mockito.when(mockQuery.getResultList()).thenReturn(stubData);
Mockito.when(entityManager.createQuery(Mockito.eq(expectedHql)、Mockito.eq(Foo.class)),然后返回(mockQuery);
List-actual=dao.findFooByName(name,otherParam);
Assert.assertSame(stubData,实际);
验证(mockQuery).setParameter(“名称”,名称);
验证(mockQuery).setParameter(“otherParam”,otherParam);
}
总之,在决定是否包括验证或存根交互或两者时,您可能需要考虑:
- 被测代码的功能:
- 可能需要存根以防止暂停执行
- 一个只做委托的方法可以通过验证得到充分证明
- 从mock转换响应的方法可能需要stubing,然后针对转换后的响应进行断言
- 等
- 您希望测试用例的具体程度:
- 一些测试路径将需要验证以提供完全覆盖
- 存根+验证可能有点过头了;查看您的代码覆盖率数字,确定额外的验证调用是在增加好处,还是只是在给您的测试用例增加混乱
这是一个意见问题,我想谢谢你详细的回答!那么,是否有任何标准或模式来编写此类测试,或者必须逐案分析?我认为这里没有标准模式,尽管“存根交互被隐式验证”肯定是一个良好的开端。这是你能感觉到的东西。
Mockito.verify(entityManager).createQuery(expectedSql, Foo.class);
Mockito.verify(mockQuery).setParameter("name", "foobar");
@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();
}
@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);
}
@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);
}