1. PACT 简介¶
1.2. 名词解释¶
消费端¶
即调用API的使用端,包括前后端分离的前端,或者调用另一个微服务的服务。
消费端本身应该是需要编写单元测试来保障自己的代码正确,此时如果需要调用服务提供端的响应,则可通过 PACT 模拟生成 Mock 服务。
而 PACT 此时将记录消费端所发送的数据及期望的返回,并生成契约文件,这是一个 JSON 文件。当然,契约文件也是可以人工编写的。
这是一举两得之事,在单元测试过程中,自然而然产生了契约。
桩服务¶
PACT 的 Mock 服务是用于在消费端单元测试时,监听发送数据和回应期望数据的服务。 如果我们需要进行前端的集成测试,此时仍然需要模拟服务提供端返回数据,则可以使用桩服务。
因此,桩服务本身,是我们日常提到的 Mock 服务,但由于在 PACT 上下文中, Mock 服务已经另有其他含义,因此改为 Stub (桩)服务。
服务器¶
PACT 的契约可以上传到 Broker 服务器,但这是一个可选项。
Broker 服务器让服务消费端和服务提供端保持一定程度的解耦,从服务器上可以看到不同的消费端, 对于同一个服务提供端的关联,可以帮助我们确保一个服务提供端针对的所有消费端,都已经通过检验。
1.3. 实战过程¶
我们以 Python 为消费端为例,描述 PACT 的实战使用过程。
安装开发依赖¶
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