2012-01-06 38 views
1

我想单元测试下面的方法如何使用thenAnswer与方法,该方法返回void

public void addRecord(Record record) 
{ 
    Myclass newObj = new Mycalss(); 
    // It creates newObj object, set some values using record object. 
    // and it adds the newObj in daatbase. 
    dataReqDao.persist(newObj); 
}  

我都嘲笑dataReqDao.persist方法,但我怎么能验证是否正确的值复制到newObj对象?我想获得newObj对象。

我认为thenAnswer将是检索newObj ie方法参数但不知道如何使用它返回void的方法的方法。

更新:
我试图

doAnswer(new Answer<Myclass>() { 
       public Myclass answer(InvocationOnMock invocation) { 
        Object[] args = invocation.getArguments(); 
        return (Myclass)args[0]; 
       } 

     }).when(dataReqDao.persist(any(Myclass.class))); 

编辑:
它应该是(感谢大卫)

doAnswer(new Answer<Myclass>() { 
        public Myclass answer(InvocationOnMock invocation) { 
         Object[] args = invocation.getArguments(); 
         return (Myclass)args[0]; 
        } 

      }).when(dataReqDao).persist(any(Myclass.class)); 
+0

在您的更新,括号内是在错误的地方。我不确定这是不是你的错误的原因,因为其余部分看起来不错。所以它应该是'doAnswer(...).when(dataReqDao).persist(...);'这有帮助吗? – 2012-01-10 22:56:41

+0

@David:谢谢大卫。其实我纠正了,但忘记更新我的问题。 – xyz 2012-01-11 05:45:41

回答

5

您可以创建自定义argument matcher,将检查的领域该对象,或使用argument captor来捕获该对象进一步检查。

例如,如下:

ArgumentCaptor<Myclass> c = ArgumentCaptor.forClass(Myclass.class); 
verify(dateReqDao).persist(c.capture()); 
Myclass newObj = c.getValue(); 

... // Validate newObj 
+0

我试过你的建议。请检查我的编辑。 – xyz 2012-01-06 09:53:19

+0

@Ajinkya:更新 – axtavt 2012-01-06 10:14:34

+0

这不会执行一个聪明的测试,因为ArgumentCaptor在调用时没有捕获该对象的状态,而只是objectId。所以即使你在dao调用之后在你的方法中使用了setter,你的测试也会是绿色的。但是一个好的测试应该会随着每个功能变化而失败我写了我的建议作为对这篇文章的回答。 – akcasoy 2015-04-10 07:57:38

0
Myclass newObj = new Myclass(); 

那行我感到困扰。如果你正在使用依赖注入,你应该让你的工厂向你发送一个对象的实例。然后,当你创建你的单元测试时,你可以让测试工厂发送一个MyClass的模拟实例,单元测试也可以访问它。然后你可以使用axtavt的捕获器来看它是否真的做了它应该做的事情。单元测试没有什么错,就像你做的那样,只是因为你知道它传入了一个这种类型的对象,所以any()是有点弱的 - 在测试中你想知道的是对象是你的目标之一,并没有被修改。

1

您需要thenAnswer(或然后,我个人比较喜欢),使其在方法调用的时间,让您可以断言/验证值的方法。

when(dataReqDao.persist(newObj)).then(new Answer<Void>() { 
     @Override 
     public Void answer(final InvocationOnMock invocation) { 
      Myclass newObjActual = (Myclass) invocation.getArguments()[0]; 

      // Control 
      assertEquals(..., newObjActual.getX()); 
      assertEquals(..., newObjActual.getY()); 
      return null; 
     } 
    }); 

// Run Test 
x.addRecord(record); 

这里是一个详细的解释:https://akcasoy.wordpress.com/2015/04/09/the-power-of-thenanswer/(用例2)

ArgumentCaptor不以巧妙的方式测试。当你改变你的方法是这样的:

public void addRecord(Record record) 
{ 
    Myclass newObj = new Mycalss(); 
    dataReqDao.persist(newObj); 

    // first persist, than set attributes 
    newObj.setX(..); 
} 

。与捕手测试仍然运行,但是它应该会失败。由于ArgumentCaptor在调用时不会捕获对象的状态,而只是捕获objectId,因此无论您是在dao调用之前还是之后设置属性,都无关紧要。然而,每次功能改变都会导致一次好的测试失败。下面是我的文章正是对这种情况:

https://akcasoy.wordpress.com/2015/02/03/how-to-ensure-quality-of-junit-tests/(上面的磕碰与然后是一个更好的办法,虽然不是一个与序方法)