如何正确使用Mockito模拟带回调的方法?
如何Mock带回调参数的方法直接触发onSuccess/onError?
现有方法实现
我有如下方法:
override fun functionToBeMocked( param: Param, onSuccess: (param: Param) -> Unit, onError: (param: Param, errorMessage: String) -> Unit ) { val response = factory.request(param) .exchange() .block() if (response?.statusCode()?.is2xxSuccessful == true) { onSuccess(param) } else if (response?.statusCode()?.isError == true) { val status = response.rawStatusCode() val body = response.bodyToMono(String::class.java).block() val errorMessage = "$status : $body" onError(param, errorMessage) } else { return } }
测试需求
我想要测试调用该方法的服务,该方法传入了指定的onSuccess和onError函数。需要Mock functionToBeMocked(),使其直接执行onSuccess(param)或onError(param)。
当前测试代码:
@Test fun test() { val failure = ParamDoc(param.id, param) whenever(repo.findAll()).thenReturn(listOf(failure)) // 此方法调用应根据测试用例执行onSuccess()或onError // whenever(mockedService.functionToBeMocked).thenAnswer.. (?) underTest.functionToBeTested() // verify(..) }
补充:factory中的request函数:
fun request(param: Param): WebClient.RequestHeadersSpec<*> { val client = WebClient .builder() .defaultHeader("API-KEY", config.apiKey) .baseUrl(config.baseUrl) .build() return client .post() .uri("/service/test") .contentType(MediaType.APPLICATION_JSON) .bodyValue(Dto.fromParam(param)) }
解决方案
使用Mockito的thenAnswer可以获取方法调用时传入的所有参数,然后直接触发对应的回调函数:
1. Mock触发onSuccess回调
whenever(mockedService.functionToBeMocked(any(), any(), any())).thenAnswer { invocation -> // 获取传入的param参数 val param = invocation.getArgument<Param>(0) // 获取onSuccess回调函数 val onSuccess = invocation.getArgument<(Param) -> Unit>(1) // 执行回调 onSuccess(param) // 方法返回值(原方法为Unit,直接返回Unit即可) Unit }
2. Mock触发onError回调
whenever(mockedService.functionToBeMocked(any(), any(), any())).thenAnswer { invocation -> val param = invocation.getArgument<Param>(0) val onError = invocation.getArgument<(Param, String) -> Unit>(2) // 传入自定义错误信息 onError(param, "自定义错误内容") Unit }
注意事项
- 确保
mockedService是通过@Mock注解或者mock(Service::class.java)创建的Mock实例 - 如果需要针对特定
Param进行Mock,可以把any()替换为eq(targetParam)来精准匹配参数
内容的提问来源于stack exchange,提问作者Christian
相关产品推荐
相关产品推荐

