Testing Vertx模拟具有处理程序的异步方法<;异步结果<&燃气轮机&燃气轮机;论点

Testing Vertx模拟具有处理程序的异步方法<;异步结果<&燃气轮机&燃气轮机;论点,testing,mocking,mockito,vert.x,Testing,Mocking,Mockito,Vert.x,我有这个数据访问接口: public interface UserDao { void loadUsers(Handler<AsyncResult<List<User>>> handler); } 公共接口UserDao{ void loadUsers(处理程序); } 在这样的服务中使用: public class UserService { private UserDao userDao; public UserService(U

我有这个数据访问接口:

public interface UserDao {

   void loadUsers(Handler<AsyncResult<List<User>>> handler);

}
公共接口UserDao{
void loadUsers(处理程序);
}
在这样的服务中使用:

public class UserService {

  private UserDao userDao;

  public UserService(UserDao UserDao) {
    this.userDao = userDao;
  }

  public void getUsers(Future<List<User>> future) {
    userDao.loadUsers( ar ->{
      if (ar.succeeded()){
        List<User> users = ar.result();
        // process users
        future.complete(users);
      }else {
        // handle the error
      }
    });
  }
}
公共类用户服务{
私有UserDao UserDao;
公共用户服务(UserDao UserDao){
this.userDao=userDao;
}
公共用户(未来){
userDao.loadUsers(ar->{
如果(ar.successed()){
列表用户=ar.result();
//进程用户
未来。完成(用户);
}否则{
//处理错误
}
});
}
}
现在,我打算对我的服务进行单元测试,并模拟数据访问层。每次调用UserDao类的getUsers方法时,我都希望返回一组固定的结果

@Test
public void testGetUsers(TestContext context) {

  Async async = context.async();

  UserDao mockUserDao = Mockito.mock(UserDao.class);

  UserService userService = new UserService(mockUserDao);
  List<User> mockResult = Arrays.asList(new User(), new User());

  /* (?) How to make mockUserDao return mockResult through its Handler argument? */

  Future<List<User>> future = Future.future();
  userService.getUsers(future);
  future.setHandler(ar -> {
    assertEquals(2, ar.result().size());
    async.complete();
  });

  async.awaitSuccess();

}
@测试
公共void testGetUsers(TestContext上下文){
Async Async=context.Async();
UserDao mockUserDao=Mockito.mock(UserDao.class);
UserService UserService=newuserservice(mockUserDao);
List mockResult=Arrays.asList(new User(),new User());
/*(?)如何使mockUserDao通过其处理程序参数返回mockResult*/
Future=Future.Future();
getUsers(未来);
future.setHandler(ar->{
资产质量(2,ar.result().size());
async.complete();
});
async.waitsuccess();
}

我该怎么做?当(serviceMock.method(any(Argument.class)))时,它不符合正常的Mockito模式。然后,作为mockResult的应答(new Result())不是通过方法返回的,而是通过处理程序返回的。

Mock
处理程序

Handler mockedHandler = mock(Handler.class);
when(mockedHandler.result()).thenReturn(mockResult);
when(userDao.loadUsers(any(Handler.class))).thenReturn(mockedHandler);
存根函数

public class TestUserDao implements UserDao {
   void loadUsers(Handler<AsyncResult<List<User>>> handler) {
     handler.apply(mockResult)
   }
}

UserDao userDao = mock(UserDao.class, AdditionalAnswers.delegatesTo(new TestUserDao()));
verify(userDao).loadUsers(any());
公共类TestUserDao实现UserDao{
void loadUsers(处理程序){
handler.apply(mockResult)
}
}
UserDao UserDao=mock(UserDao.class,AdditionalAnswers.delegatesTo(newtestuserdao());
验证(userDao).loadUsers(any());

您可以使用ArgumentCaptor检查是否使用非空处理程序调用了loadUsers()。ArgumentCaptor允许您访问处理程序 您可以向其传递准备好的结果(成功或失败的结果)

AsyncResult yourResult=//成败
ArgumentCaptor captor=ArgumentCaptor.forClass(Handler.class);
Mockito.verify(userDao.loadUsers(captor.capture());
Handler=captor.getValue();
handler.handle(你的结果);

这不起作用,因为loadUsers方法没有返回处理程序。这就是我问题的全部要点。请看我问题中的最后一句话。只是一个友好的评论,当涉及到DAO层时,沿着发送
Future
的路线,当代码库开始增长时,事情真的变得很难理解和解释,如果您真的刚刚开始您的项目,我的建议是使用
reactivejava
。如果您愿意,我可以为您添加描述事物的代码片段。
AsyncResult<List<User>> yourResult = ... //success or failure

ArgumentCaptor<Handler<AsyncResult<List<User>>>> captor = ArgumentCaptor.forClass(Handler.class);
Mockito.verify(userDao).loadUsers(captor.capture());
Handler<AsyncResult<List<User>>> handler = captor.getValue();
handler.handle(yourResult);