1. PACT 简介¶
1.2. 名词解释¶
消费端¶
即调用API的使用端,包括前后端分离的前端,或者调用另一个微服务的服务。
消费端本身应该是需要编写单元测试来保障自己的代码正确,此时如果需要调用服务提供端的响应,则可通过 PACT 模拟生成 Mock 服务。
而 PACT 此时将记录消费端所发送的数据及期望的返回,并生成契约文件,这是一个 JSON 文件。当然,契约文件也是可以人工编写的。
这是一举两得之事,在单元测试过程中,自然而然产生了契约。
桩服务¶
PACT 的 Mock 服务是用于在消费端单元测试时,监听发送数据和回应期望数据的服务。 如果我们需要进行前端的集成测试,此时仍然需要模拟服务提供端返回数据,则可以使用桩服务。
因此,桩服务本身,是我们日常提到的 Mock 服务,但由于在 PACT 上下文中, Mock 服务已经另有其他含义,因此改为 Stub (桩)服务。
服务器¶
PACT 的契约可以上传到 Broker 服务器,但这是一个可选项。
Broker 服务器让服务消费端和服务提供端保持一定程度的解耦,从服务器上可以看到不同的消费端, 对于同一个服务提供端的关联,可以帮助我们确保一个服务提供端针对的所有消费端,都已经通过检验。
1.3. 实战过程¶
我们以 Python 为消费端为例,描述 PACT 的实战使用过程。
扫描二维码关注公众号,回复:
5461720 查看本文章
安装开发依赖¶
pip3 install pact-python --user
export PATH=$PATH:~/Library/Python/3.7/bin
编写单元测试¶
假定该单元测试的文件名为 app-mlcproxy.py 。
import atexit, unittest
from pact import Consumer, Provider, Like, EachLike, Term from pact.matchers import get_generated_values import requests pact = Consumer('app').has_pact_with(Provider('mlcproxy'), host_name='localhost', port=5431, pact_dir='./pacts') pact.start_service() atexit.register(pact.stop_service) def user(): return { 'uid': '122112221', 'name': '苏渝', 'mobile_phone': '18980472890', 'idticket_id': '510108196507212137', 'payment_channel': '11', 'pay_id': '112kakak12222', 'auth_code': '122211' } def expected_ok(uid): return { 'code': 'SUCCESS', 'msg': '成功', 'result_list': [ { 'result': '01', 'uid': uid } ] } def expected_fail(uid): return { 'code': 'FAIL', 'msg': '失败', 'result_list': [ { 'result': '02', 'uid': uid } ] } def json_header(): return { 'Content-Type': 'application/json' } class UsersContract(unittest.TestCase): def test_update(self): body = user() body['userpush_type'] = '02' ok = expected_ok(body['uid']) fail = expected_fail(body['uid']) body_ok = body.copy() body_ok['idticket_id'] = '610425197608030318' body_idcard17 = body.copy() body_idcard17['idticket_id'] = '61042519760803031' # 身份证差一位 body_idcard_wrong = body.copy() body_idcard_wrong['idticket_id'] = '61042519760803031X' # 身份证检校验码不正确 (pact .given('success') .upon_receiving