我有一个具有这些结构的类,我需要测试OnRequestListOfLunchsFinished接口的行为
@Override
public void getListOfLunchs(final OnRequestListOfLunchsFinished callback) {
zip().onErrorResumeNext(new Function<Throwable, ObservableSource<? extends LunchServiceResponse>>() {
@Override
public ObservableSource<? extends LunchServiceResponse> apply(@NonNull Throwable throwable) throws Exception {
callback.onError(new RuntimeException(throwable));
callback.onEnd();
return Observable.empty();
}
}).subscribe(new Consumer<LunchServiceResponse>() {
@Override
public void accept(LunchServiceResponse response) throws Exception {
List<Lunch> result = new ArrayList<>();
List<IngredientResponseVO> ingredients = response.getIngredients();
Map<Integer, Ingredient> hash = new HashMap<Integer, Ingredient>();
for (IngredientResponseVO vo : ingredients)
hash.put(vo.id, new Ingredient(vo.id, vo.name, new BigDecimal(vo.price.toString()), vo.image));
for(InfoLunchResponseVO vo: response.getLunch()){
Lunch lunch = new Lunch();
lunch.setId(vo.id);
lunch.setImage(vo.image);
lunch.setName(vo.name);
for(Integer id : vo.ingredients){
Ingredient ingredient = hash.get(id);
lunch.addIngredient(ingredient);
}
result.add(lunch);
}
callback.onSuccess(result);
callback.onEnd();
}
});
callback.onStart();
}
private Observable<LunchServiceResponse> zip(){
return Observable.zip(getRequestOfListOfLunchs(), getRequestOfListOfIngredients(), new BiFunction<List<InfoLunchResponseVO>, List<IngredientResponseVO>, LunchServiceResponse>() {
@Override
public LunchServiceResponse apply(@NonNull List<InfoLunchResponseVO> infoLunchResponseVOs, @NonNull List<IngredientResponseVO> ingredientResponseVOs) throws Exception {
return new LunchServiceResponse(infoLunchResponseVOs, ingredientResponseVOs);
}
});
}我有这个测试方法
@Test
public void teste(){
List<IngredientResponseVO> ingredients = Collections.emptyList();
List<InfoLunchResponseVO> lunchs = Collections.emptyList();
when(mockApi.getListOfIngredients()).thenReturn(Observable.just(ingredients));
when(mockApi.getLunchs()).thenReturn(Observable.just(lunchs));
mockImplementation.getListOfLunchs(callback);
InOrder order = inOrder(callback);
order.verify(callback).onStart();
order.verify(callback).onSuccess(anyList());
order.verify(callback).onEnd();
order.verifyNoMoreInteractions();
}但我收到了一个异常:
org.mockito.exceptions.verification.VerificationInOrderFailure:
Verification in order failure
Wanted but not invoked:
callback.onSuccess(<any>);如果我这样做:
callback.onStart();
callback.onSuccess(Collections.<Lunch>emptyList());
callback.onEnd();
InOrder order = inOrder(callback);
order.verify(callback).onStart();
order.verify(callback).onSuccess(anyList());
order.verify(callback).onEnd();
order.verifyNoMoreInteractions();这是可行的。
如何仅验证模拟callback的调用
发布于 2017-08-18 13:52:09
您只需使用InOrder对象,而不是。
mockImplementation.getListOfLunchs(callback);
Mockito.verify(callback).onStart();
Mockito.verify(callback).onSuccess(anyList());
Mockito.verify(callback).onEnd();
Mockito.verifyNoMoreInteractions();发布于 2017-08-20 09:14:06
AFAICS问题不在于测试,而在于你对测试结果的阅读(跳过:我相信它在你的代码中发现了一个bug )。
在实际代码中,您的getListOfIngredients和getLunchs可能会执行一些网络请求,即它们与对getListOfLunchs和(其内部的zip)的调用是异步的。因此,在实际代码中,在调用者线程上立即调用onStart,而稍后调用onSucess和onEnd。然而,在您的测试中,您使用synchronous Observable.just来模拟这些API调用,因此执行顺序是不同的:首先调用onSuccess,然后调用onEnd,最后调用onStart (如果您将模拟的callback替换为一个自定义的API,它只在每次调用中记录方法名称,则可以很容易地验证这一点)。
你可能已经预料到,由于你使用了verifyNoMoreInteractions,你会得到一个关于错误的onStart顺序的错误。不幸的是,这不是它的工作方式。由于您的订单验证是在较早的时间指定的,因此会在较早的时间进行检查。在这些检查中,还没有“不再”的限制。因此,发生的事情大致如下:
调用
onSucess。那该怎么办呢?首先,我想说的是,这个失败的测试确实在你的代码中发现了一个非常真实的bug。假设在将来的某个时刻,有人向你的应用编程接口添加了一个缓存层,所以有时getListOfIngredients和getLunchs会立即返回一个同步的结果。在这种情况下,您的代码违反了应该首先调用onStart的OnRequestListOfLunchsFinished的约定。所以正确的方法是修复你的代码。一种明显但可能的错误方法是移动线条
callback.onStart();添加到方法的开头。(为什么它可能是错误的?你的zip能抛出异常吗?另一种方法是使用onEnd做同样的事情,即按正确的顺序将其复制到成功和错误处理代码中。
https://stackoverflow.com/questions/45747197
复制相似问题