说到Spring Boot 单元测试主要有两个主流集成分别是Mockito
,Junit
,这个各有特点,在实际开发中,我想要的测试框架应该是这个框架集成者。要有Junit
能够运行某一个单元用例,完整的项目环境,又需要Mockito
能对某一个依赖进行注入,指定返回值内容。可惜实际中这两个框架根本不能同时运行的。突然想到可以通过AOP的环绕通知来实现Mock注入功能,覆盖某一个方法返回值。
现在有一个Feign接口AService,实际情况我们环境根本就没有这个服务,调用这个方法一定会报错的。通过代理技术的环绕通知覆盖返回值,能让方法正常调用。具体代码实现如下
Feign 代码
@FeignClient(name = "application-a")
public interface AFeignService {
@RequestMapping("/url/path/get")
Result<Object> get();
}
测试用例
@SpringBootTest
@Slf4j
class AFeignServiceTest {
@Autowired
private AFeignService aFeignService;
@Test
void get() {
Result<Object> result = aFeignService.get();
log.info(JSONObject.toJSONString(result));
}
}
执行测试用例,一定会出错,缺少代理方法
在test中添加代理配置类
@Aspect
@Slf4j
public class AspConfig {
@Pointcut("execution(* com..AFeignService.get(..))")
public void pointcue(){
}
@Around("pointcue()")
public Object overrideReturnValue(ProceedingJoinPoint joinPoint) throws Throwable {
log.info("AspConfig.overrideReturnValue execute .................");
//joinPoint.proceed(); 不调用原来方法
ErpReturnDTO dto = new ErpReturnDTO();
dto.setStatus(200);
dto.setSuccess(true);
dto.setMessage("success");
dto.setData(new ArrayList<>());
Result<ErpReturnDTO> result = Result.succeed(dto);
return result;
}
}
添加切面配置类,这是用于测试用途的代码,不能写在src/代码上,而是使用ImportBeanDefinitionRegistrar,在测试中引用进来。
ImportBeanDefinitionRegistrar: 是Spring提供接口,运行开发者添加自定义添加自己的配置类,Spring Boot组件扩展就是通过这个接口来实现的。
public class TestAopImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
BeanDefinitionBuilder definitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(AspConfig.class);
GenericBeanDefinition definition = (GenericBeanDefinition) definitionBuilder.getRawBeanDefinition();
registry.registerBeanDefinition(AspConfig.class.getName(), definition);
}
}
在原来的单元测试引入代理配置就可以了
@SpringBootTest
@Slf4j
@Import(TestAopImportBeanDefinitionRegistrar.class)
class AFeignServiceTest
再次运行测试用例,没有异常,并且返回对象成功打印出来
{"code":0,"data":{"data":[],"message":"success","status":200,"subMessage":"success","success":true},"msg":"操作成功","success":true}
有这个代理配置,就可以在平常的开发中,对单元测试中的依赖进行代理覆盖返回值,达到Mock某个方法的返回值效果了。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。