11import os
22
33import pytest as pytest
4- from pact import Like , MessageConsumer , Provider , Term
5-
4+ import json
5+ from pact .v3 .pact import Pact
6+ from pact import matchers
7+ from pathlib import Path
8+ from typing import (
9+ TYPE_CHECKING ,
10+ Any ,
11+ )
612from src .product .product_service import receive_product_update
13+ from src .product .product import Products
714
815CONSUMER_NAME = "pactflow-example-consumer-python-sns"
916PROVIDER_NAME = os .getenv ("PACT_PROVIDER" , "pactflow-example-provider-js-sns" )
1017PACT_DIR = os .path .join (os .path .dirname (os .path .realpath (__file__ )),".." ,".." , "pacts" )
1118
12- @pytest .fixture (scope = "session " )
13- def consumer ():
19+ @pytest .fixture (scope = "module " )
20+ def handler ():
1421 return receive_product_update
1522
16-
17- @pytest .fixture (scope = "session" )
23+ @pytest .fixture (scope = "module" )
1824def pact ():
19- pact = MessageConsumer (
20- CONSUMER_NAME ,
21- ).has_pact_with (
22- Provider (PROVIDER_NAME ),
23- pact_dir = PACT_DIR ,
24- )
25+ pact_dir = Path (Path (__file__ ).parent .parent .parent / "pacts" )
26+ pact = Pact (CONSUMER_NAME , PROVIDER_NAME )
27+ yield pact .with_specification ("V3" )
28+ pact .write_file (pact_dir , overwrite = True )
29+
30+ @pytest .fixture
31+ def verifier (
32+ handler ,
33+ ):
34+ """
35+ Verifier function for the Pact.
2536
26- yield pact
37+ This function is passed to the `verify` method of the Pact object. It is
38+ responsible for taking in the messages (along with the context/metadata)
39+ and ensuring that the consumer is able to process the message correctly.
40+
41+ In our case, we deserialize the message and pass it to our message
42+ handler for processing.
43+ """
44+
45+ def _verifier (msg : str | bytes | None , context : dict [str , Any ]) -> None :
46+ assert msg is not None , "Message is None"
47+ data = json .loads (msg )
48+ print (
49+ "Processing message: " ,
50+ {"input" : msg , "processed_message" : data , "context" : context },
51+ )
52+ handler (data )
53+ yield _verifier
2754
2855@pytest .mark .asyncio
29- async def test_receive_a_product_update (pact , consumer ):
56+ async def test_receive_a_product_update (pact , handler , verifier ):
3057 event = {
31- "id" : Like ( "some-uuid-1234-5678" ) ,
32- "type" : Like ( "Product Range" ) ,
33- "name" : Like ( "Some Product" ) ,
34- "event" : Term ( matcher = "^(CREATED| UPDATED|DELETED)$" , generate = "UPDATED" )
58+ "id" : "some-uuid-1234-5678" ,
59+ "type" : "Product Range" ,
60+ "name" : "Some Product" ,
61+ "event" : " UPDATED"
3562 }
3663 (
3764 pact
38- .expects_to_receive ("a product event update" )
39- .with_content (event )
40- .with_metadata ({"contentType" : "application/json" , 'topic' : 'products' })
65+ .upon_receiving ("a product event update" , "Async" )
66+ .with_body (json .dumps (event ),
67+ "application/json" )
68+ .with_matching_rules (
69+ {
70+ "body" : {
71+ "$.event" : {
72+ "combine" : "AND" ,
73+ "matchers" : [
74+ {
75+ "match" : "regex" ,
76+ "regex" : "^(CREATED|UPDATED|DELETED)$"
77+ }
78+ ]
79+ },
80+ "$.id" : {
81+ "combine" : "AND" ,
82+ "matchers" : [
83+ {
84+ "match" : "type"
85+ }
86+ ]
87+ },
88+ "$.name" : {
89+ "combine" : "AND" ,
90+ "matchers" : [
91+ {
92+ "match" : "type"
93+ }
94+ ]
95+ },
96+ "$.type" : {
97+ "combine" : "AND" ,
98+ "matchers" : [
99+ {
100+ "match" : "type"
101+ }
102+ ]
103+ },
104+ "$.version" : {
105+ "combine" : "AND" ,
106+ "matchers" : [
107+ {
108+ "match" : "type"
109+ }
110+ ]
111+ }
112+ }
113+ }
114+ )
115+ .with_metadata ({"topic" : "products" })
41116 )
42-
43- with pact :
44- await consumer (event )
117+ pact .verify (verifier , "Async" )
0 commit comments