我有以下代码进行单元测试:
persistence.save
我想验证第一次调用entity.getDate()
null
时返回Mockito.verify(/*...*/)
。
因此我无法使用foo
因为当时方法entity.setDate(Date)
已经完成且 </script>
<script>
var app = angular.module('myApp',[]);
app.directive('tagInputType', function() {
return {
restrict: 'E',
scope: { tags: '=' },
template:
'<div class="tags">' +
'<a ng-repeat="(idx, tag) in tags" class="tag" ng-click="remove(idx)">{{tag}}</a>' +
'</div>' +
'<input type="text" placeholder="Add a tag..." ng-model="new_value"></input> ' +
'<input type="button" value="Add" ng-click="add()"></input>',
link: function ( $scope, $element ) {
// var input = angular.element( $element.children()[1] );
$scope.add = function() {
$scope.tags.push( $scope.new_value );
$scope.new_value = "";
};
$scope.remove = function ( idx ) {
$scope.tags.splice( idx, 1 );
};
input.bind( 'keypress', function ( event ) {
if ( event.keyCode == 13 ) {
$scope.$apply( $scope.add );
}
});
}
};
});
app.controller('MainCtrl', function ( $scope ) {
$scope.tags = { "value1":"angular","value2":"html"};
});
</script>
已被调用。
所以我认为我需要在调用发生时对调用进行验证。我如何使用Mockito做到这一点?
答案 0 :(得分:6)
我创建了以下Answer
实现:
public class CapturingAnswer<T, R> implements Answer<T> {
private final Function<InvocationOnMock, R> capturingFunction;
private final List<R> capturedValues = new ArrayList<R>();
public CapturingAnswer(final Function<InvocationOnMock, R> capturingFunction) {
super();
this.capturingFunction = capturingFunction;
}
@Override
public T answer(final InvocationOnMock invocation) throws Throwable {
capturedValues.add(capturingFunction.apply(invocation));
return null;
}
public List<R> getCapturedValues() {
return Collections.unmodifiableList(capturedValues);
}
}
此答案捕获正在进行的调用的属性。然后capturedValues
可用于简单断言。该实现使用Java 8 API。如果不可用,则需要使用能够将InvocationOnMock
转换为捕获值的接口。测试用例中的用法如下:
@Test
public void testSomething() {
CapturingAnswer<Void,Date> captureDates = new CapturingAnswer<>(this::getEntityDate)
Mockito.doAnswer(captureDates).when(persistence).save(Mockito.any(Entity.class));
service.foo();
Assert.assertNull(captureDates.getCapturedValues().get(0));
}
private Date getEntityDate(InvocationOnMock invocation) {
Entity entity = (Entity)invocation.getArguments()[0];
return entity.getDate();
}
使用Mockitos Answer
无法实现所呈现的ArgumentCaptor
实现所执行的捕获,因为这仅在调用被测方法之后使用。
答案 1 :(得分:1)
在我原来的评论中,这是我想到的答案。
要嘲笑的课程:
class MockedClass{
void save(SomeBean sb){
//doStuff
}
}
我们需要验证Date对象的类是null。
class SomeBean{
Date date;
Date getDate(){return date;}
void setDate(Date date){this.date=date;}
}
受测试的课程:
class TestClass{
MockedClass mc;
TestClass(MockedClass mc){this.mc = mc;}
void doWork(){
SomeBean sb = new SomeBean();
mc.save(sb);
sb.setDate(new Date());
mc.save(sb);
}
}
测试用例:
@Test
public void testAnswer(){
MockedClass mc = Mockito.mock(MockedClass.class);
Mockito.doAnswer(new Answer<Void>(){
boolean checkDate = true;
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
SomeBean sb = (SomeBean) invocation.getArguments()[0];
if(checkDate && sb.getDate() != null){
throw new NullPointerException(); //Or a more meaningful exception
}
checkDate = false;
return null;
}}).when(mc).save(Mockito.any(SomeBean.class));;
TestClass tc = new TestClass(mc);
tc.doWork();
}
第一次通过这个Answer
(我应该在我的原始注释中使用的术语),如果date不为null,这将抛出异常并使测试用例失败。第二次,checkDate
将为false,因此不会执行检查。