在微服务架构下,将测试分为单元测试、集成测试、组件测试、端到端测试。
单元测试
即对最小可测试单元的测试。作者认为通常是面向类或者一组类的,但是在常见的单元测试讲解中,通常将“单元”定义为方法级别。与常见的单元测试观点相同,作者建议单元测试仅仅测试被测单元的逻辑,对于被测单元调用的其他方法应该通过mock的方式进行模拟。
集成测试
在很长的时间内,我将集成测试理解为服务化架构下针对某支接口的测试(面向某个服务,不面向网关)。事实上,集成测试解决的问题更多是单元测试无法解决的问题,同时,集成测试的执行不应依赖于服务的启动,因为服务启动的代价非常昂贵、并且通过启动服务的方式进行测试不够灵活。
一直以来没有很好测试思路的持久层测试,就可以通过集成测试解决。在测试前需要准备一套可用的数据存储环境(数据库或者各种分布式缓存),通过Junit等组件完成数据层的持久测试,在测试完成后要注意将数据恢复。
对于服务的集成测试则可以通过契约测试完成。建议的契约测试假设存在两种角色:消费者Consumer与提供者Provider. 契约测试可以很好地解决这两种角色在服务层面的集成测试问题(作为Consumer,需要测试调用Provider服务并正确处理返回的过程;作为Provider需要测试正确响应Consumer调用的逻辑。总的来看都是被测对象与服务外部产生关系的测试。)流程如下:
a. 消费者按照api定义编写契约测试案例,并提交至提供者源码库
b. 服务提供方利用消费者编写的契约测试案例生成测试代码并对编写的服务进行测试
c. 服务提供方将经过测试的契约通过maven或其他工具发布
d. 消费者采用服务提供方发布的契约进行测试
事实上,在测试相关的两章中,书中所列举的例子并没有完整实现全部流程。以Spring Cloud Contract为例的例子更多是上述步骤中a\b\d步骤的时间,并没有服务提供方反向发布验证过契约的过程。
不论如何,这里消费者驱动的契约测试的核心思想在于,当服务提供方发布接口之后,由消费者按照理解编写契约(测试案例),然后服务提供方按照该契约生成测试代码来测试接口。这里关键在于由消费者按照理解编写契约,事实上完成了双方对于同一个接口定义的沟通(假设提供方在收到契约后发现,消费者理解有误还可以进一步沟通,或者采用上述步骤中的c,来实现反馈)。而假设通过传统的挡板方式,虽然消费者按照自己的理解进行了自己的测试,但是并不能保证自己的理解是服务提供方想要表达的意思。
此外,对于类似异步通信、通过发布\订阅模式等与应用外部组件或系统通信的代码,也可以采用类似的方案进行契约测试。
组件测试
这里所说的组件测试,即对某支接口进行验收测试。书中建议采用各类自动化的方式执行组件测试,结合目前的开发实际,可以采用如Jmeter等工具实现组件测试。注意这里在测试过程中,对于持久层或者kafka等通信组件,需要具备一套支持组件测试的环境,而对于依赖的其他服务,则可以采用契约测试中经过验证的挡板来进行模拟。
端到端测试
端到端测试即对待测功能在各服务、组件完全正常运行的情况进行测试,这里更类似于功能测试或者UAT测试。实际上,作者建议,在经过完善的单元、集成、组件测试后,端到端测试应该是少量的案例并且应该是自动化的。
总之,要实现一套好微服务架构风格应用体系,做好上述测试过程,并将各个测试环节自动化是必不可少的。借用作者的一句话,将应用推向单体深渊的最快途径就是不做自动化测试。