微服务架构之自动化测试全链路设计Word文件下载.docx
- 文档编号:19323376
- 上传时间:2023-01-05
- 格式:DOCX
- 页数:13
- 大小:26.86KB
微服务架构之自动化测试全链路设计Word文件下载.docx
《微服务架构之自动化测试全链路设计Word文件下载.docx》由会员分享,可在线阅读,更多相关《微服务架构之自动化测试全链路设计Word文件下载.docx(13页珍藏版)》请在冰豆网上搜索。
callback
接口、交易链路上的
marketing
接口、配送
routing
接口等。
http:
//f—1。
cc
这里给大家分享我们目前正在进行中的
marketing-cloud(营销云)规则引擎
项目。
marketing-cloud
提供了一些营销类业务,有
团购、优惠券、促销
等,但是我们的业务方需要有自己个性化的营销活动玩法,我们需要在
marketing—cloud
规则引擎
中抽象出业务方营销活动的返回信息,同时打通个性化营销活动与公共交易、结算环节,形成一个完整的业务流。
这是一个
逻辑架构图,跟我们主题相关的就是
营销规则引擎
,他就是我们这里所说的合理的业务场景。
在整个正向下单过程中,营销规则引擎要肩负起既要提供
内的共用营销活动,还需要桥接外部营销中心的各类营销玩法,外部的营销中心会有多个,目前我们主要有两个。
由于这篇文章不是介绍营销平台怎么设计,所以这里不打算扩展话题。
主要是起到抛砖引玉的目的,平台型的业务会存在各种各样的对外系统依赖的业务场景。
文章接下来的部分将展开
marketing-cloud规则引擎
在打通测试链路上的实践.
开发阶段
unitTestmock
外部依赖
在开发阶段,我们会经常性的编写单元测试来测试我们的逻辑,在编写
的时候都需要
mock
周边的依赖,mock
出来的对象分为两种类型,一种是不具有
Assert
逻辑的
stub桩
对象,还有一种就是需要支持
的
mocker
模拟对象。
但是我们也不需要明显区分他们,两者的区别不是太明显,在编码规范内可能需要区分。
我们关心的是如何解决对象之间的依赖问题,各种
框架其实提供了很多非常好用的工具,我们可以很轻松的
周边的依赖。
given(marketingService。
mixMarketingActivity(anyObject())).willReturn(stubResponse);
RuleCalculateResponseresponse=this.ruleCalculatorBiz。
ruleCalculate(request);
这里我们
了
marketingService.mixMarketingActivity()
方法.
Java
世界里提供了很多好用的
框架,比较流行好用的框架之一
mockito
可以轻松
mockService
层的依赖,当然除了
之外还有很多优秀的
框架。
这些框架大同小异,编写
最大的问题就是如何重构逻辑使之更加便于测试,也就是代码是否具备很好的可测试性,是否已经消除了绝大多数
private
方法,private
方法是否有某些指责是我们没有捕捉到业务概念.
连调阶段
在我们完成了所有的开发,完善的单元测试保证了我们内部的逻辑是没有问题的(当然这里不讨论
unitTest的
case
的设计是否完善情况)。
现在我们需要对接周边系统开发进行连调了,这个周边系统还是属于本平台之类的其他支撑系统。
比如我们的
marketing—cloud规则引擎系统
与
下单系统
之间的关系。
在开发的时候我们编写
是顺利的完成了开发解决的验证工作,但是现在面对连调问题.
系统需要正式的跑起来,但是我们缺乏对外部营销中心的依赖,我们怎么办。
其实我们也需要在连调阶段
外部依赖,只不过这个
的技术和方法不是通过
框架来支持,而是需要我们自己来设计我们的整个服务的开发架构.
首先要能识别本次
request
是需要
的,那就需要某种
mockparameter
参数来提供识别能力。
我们来看下
marketing—cloud营销规则引擎
在这块的一个初步尝试。
publicinterfaceCCMarketingCentralFacade{
CallResponsecallMarketingCentral(CallRequestrequest);
}
publicinterfaceClassMarketingCentralFacade{
CallResponsecallMarketingCentral(CallRequestrequest);
}
营销规则引擎使用
RestEasyclientapi
作为
rest
调用框架。
在正常逻辑下,我们会根据营销路由
key
来决定调用哪个公司的营销中心接口,但是由于我们在开发这个项目的时候暂时业务方还没有存在的地址让我们对接,所以我们自己做了
mockfacade,来解决连调问题。
publicclassCCMarketingCentralFacadeMockerimplementsCCMarketingCentralFacade{
@Override
publicCallResponsecallMarketingCentral(CallRequestrequest){
CallResponseresponse=.。
.
MarketingResultDtomarketingResultDto=。
.。
marketingResultDto.setTotalDiscount(newBigDecimal("
90.19”));
marketingResultDto.setUseTotalDiscount(true);
response。
getData().setMarketingResult(marketingResultDto);
returnresponse;
}
publicclassClassMarketingCentralFacadeMockerimplementsClassMarketingCentralFacade{
CallResponseresponse=。
MarketingResultDtomarketingResultDto=.。
marketingResultDto.setUseCoupon(true);
marketingResultDto.setTotalDiscount(null);
marketingResultDto。
setUseTotalDiscount(false);
List〈MarketingProductDiscountDto>
discountDtos=.。
request.getMarketingProductTagsParameter()。
getMarketingTags().forEach(item-〉{
MarketingProductDiscountDtodiscountDto=...
discountDto。
setProductId(item。
getProductID());
。
..
discountDtos。
add(discountDto);
});
我们定义了两个
类,都是一些测试数据,就是为了解决在连调阶段的问题,也就是在
DEV
环境上的依赖问题.
有了
mockfacade
之后就需要
定义
参数了。
publicabstractclassBaseRequestimplementsSerializable{
publicMockParametermockParameter;
publicclassMockParameter{
/**
*mockcc营销调用接口
*/
publicBooleanmockCCMarketingInterface;
/**
*mockclass营销调用接口
*/
publicBooleanmockClassMarketingInterface;
*是否自动化测试mock
publicBooleanuseAutoTestMock;
*测试mock参数
publicStringtestMockParam;
我们暂且忽略通用型之类的设计,这里只是我们在赶项目的情况下做的一个迭代尝试,等我们把这整个流程都跑通了再来考虑重构提取框架.
有了输入参数,我们就可以根据参数判断来动态注入
mockfacade。
自动化测试阶段
需求
我们继续向前推进,过了连调阶段紧接着就进入测试环节,现在基本上大多数互联网公司都是自动化的测试,很少在有手动的,尤其是后端系统。
那么在
autoTest
阶段面临的一个问题就是,我们需要一个公共的
地址,这个测试地址是不变的,我们在自动化测试下
facadebean
的地址就是这个地址,这个地址输出的值需要能够对应到每次自动化脚本执行的上下文中。
我们有很多微服务系统来组成一个平台,每个服务都有依赖的第三方接口,原来在自动化测试这些服务的时候都需要去了解业务方系统的接口、DB、前台入口等,因为在编写自动化脚本的时候需要同步创建测试数据,最后才能
Assert.
这个跨部门的沟通和协作效率严重低下,而且人员变动、系统变动都会直接影响上线周期,这里绝对值得创新来解决这个效率严重阻塞问题。
@Value("
${marketing.cloud。
business.access。
url.mock}"
)privateStringmockUrl;
/**
*自动化测试mockerbean
@Bean("
CCMarketingCentralFacadeTestMock"
publicCCMarketingCentralFacadeCCMarketingCentralFacadeTestMock(){
RestClientProxyFactoryBean<
CCMarketingCentralFacade〉restClientProxyFactoryBean。
restClientProxyFactoryBean.setBaseUri(this。
mockUrl);
.。
/**
*自动化测试mockerbean
@Bean(”ClassMarketingCentralFacadeTestMock"
publicClassMarketingCentralFacadeClassMarketingCentralFacadeTestMock(){
ClassMarketingCentralFacade>
restClientProxyFactoryBean..。
restClientProxyFactoryBean.setBaseUri(this.mockUrl);
.。
}
这里的
mockUrl
就是我们抽象出来的统一的
地址,在前面的
中有一个
useAutoTestMockBoolean
类型的参数,如果当前请求此参数为
true,我们将动态注入自动化测试
mockbean
,后续的所有调用都会走到
指定的地方。
autoTestMockGateway
浮出水面
到目前为止,我们遇到了自动化测试统一的
地址要收口所有微服务在这方面的需求。
现在最大的问题就是,所有的微服务对外依赖的
response
都不相同,自动化脚本在执行的时候预先创建好的
要能适配到当前测试的上下文中。
比如,营销规则引擎,我们的自动化脚本在创建一个订单的时候需要预先构造好当前商品(比如,productID:
101010),在获取外部营销中心提供的活动信息和抵扣信息的
,最后才能去
Assert订单的金额和活动信息记录是否正确,这就是一次
autoTestcontext
有两种方式来识别当前
,一种是在
执行的时候确定商品ID,最后通过商品ID来获取
还有一种就是支持传递
autoTestmock
参数给到
指定的服务,可以使用这个参数来识别当前测试上下文。
一个测试
可能会穿过很多微服务,这些所有的依赖服务可能都需要预设
mockresponse,这基本上是一劳永逸的。
所以,我们抽象出了
autoTestMockGateway(自动化测试mock网关服务)
,在整个自动化测试环节还有很多需要支持的工作,服务之间的鉴权,鉴权
mock,加解密,加解密
mock,自动化测试
交替并行执行等。
作为工程师的我们都希望用系统化、工程化的方式来解决整体问题,而不是个别点状问题。
有了这个
mockgateway
我们可以做很多事情,也可以普惠所有需要的其他部门。
在一次
里构造好
mockresponse,然后通过
来动态识别具体的来源服务进行路由、鉴权、加解密等操作。
MockGateway
是一个支点,我相信这个支点可以撬动很多测试空间和创新能力。
轻量级版本实现
接下来我们将展示在
中的初步尝试.
整体逻辑架构
自动化脚本在每跑一个
的时候会创建当前
对应的
autoTestContext,这里面都是一些
metadata,用来表示这个
中所有涉及到的微服务系统哪些是需要走
的。
mockGateway
中所有的配置都是有一个
autoTestContext
所对应,如果没有
说明是所有
共用。
将mockparameter纳入服务框架标准requestcontract
要想打通整个微服务架构中的所有通道,就需要在标准
requestcontract
mockParameter
,这是这一切的前提。
服务与服务之间调用走标准微服务
requestcontract,服务与外部系统的依赖可以选择走
HTTPHeader,也可以选择走标准
,就要看我们的整个服务框架是否已经覆盖所有的产线及一些遗留系统的问题.
publicMockParametermockParameter;
BaseRequest
是所有
的基类,这样才能保证所有的请求能够正常的传递.
使用
AOP+RestEasyHttpClientRequestSPI
初步实现Mock
整个系统的开发架构分层依赖是:
facade-〉biz—〉service,基本的所有核心逻辑都是在
service
中,请求的
requestdto
最多不能越界到
层,按照规范讲
顶多滞留在
biz
层,但是在互联网的世界中一些都是可以快速迭代的,并不是多么硬性规定,及时重构是偿还技术债务的主要方法。
前面我们已经讲过,我们采用的
RPC
框架是
RestEasy+RestEasyclient
,我们先来看下入口的地方。
@Component@Path("
v1/calculator/"
)publicclassRuleCalculatorFacadeImplextendsBaseFacadeimplementsRuleCalculatorFacade{
@MockFacade(Setting=MockFacade.SETTING_REQUEST_MOCK_PARAMETER)
publicRuleCalculateResponseruleCalculate(RuleCalculateRequestrequest){
再看下
对象.
@ComponentpublicclassMarketingServiceImplextendsMarketingBaseServiceimplementsMarketingService{
@MockFacade(Setting=MockFacade.SETTING_FACADE_MOCK_BEAN)
publicMarketingResultonlyExtendMarketingActivity(Marketing.。
ParametertagsParameter){
我们重点看下
@MockFacade
annotation声明.
@Target({ElementType。
METHOD})@Retention(RetentionPolicy.RUNTIME)public@interfaceMockFacade{
StringSETTING_REQUEST_MOCK_PARAMETER="
setting_request_mock_parameter"
;
StringSETTING_FACADE_MOCK_BEAN="
setting_facade_mock_bean”;
StringSetting();
通过这个annotation我们的主要目的就是将
放到
ThreadLocal
中去和请求处理完时的清理工作。
还有一个功能就是
层的
处理。
@Aspect
@Component
@Slf4jpublicclassMockMarketingFacadeInterceptor{
@Before("
@annotation(mockFacade)”)
publicvoidbeforeMethod(JoinPointjoinPoint,MockFacademockFacade){
StringsettingName=mockFacade。
Setting();
if(MockFacade.SETTING_REQUEST_MOCK_PARAMETER。
equals(settingName)){
Object[]args=joinPoint.getArgs();
if(args==null)return;
List〈Object>
argList=Arrays。
asList(args);
argList。
forEach(item—>
{
if(iteminstanceofBaseRequest){
BaseRequestrequest=(BaseRequest)item;
if(request。
getMockParameter()!
=null){
MarketingBaseService。
mockParameterThreadLocal.set(request。
getMockParameter());
log.info(”-——-settingmockparameter:
{}”,JSON.toJSONString(request.getM
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 微服 架构 自动化 测试 全链路 设计