I'm new to both python and contract testing. I'm trying to test my consumer application using pact-python
.
This is the test file test_posts_controller.py
import unittest
import atexit
from pact import Consumer, Provider, Term
import requests
pact = Consumer('Consumer').has_pact_with(Provider('Provider'))
pact.start_service()
atexit.register(pact.stop_service)
class GetPostsContract(unittest.TestCase):
def test_get_all_posts(self):
expected = {
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
"body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
}
(pact
.given('posts exist')
.upon_receiving('a request for post by id')
.with_request('GET', '/posts/1')
.will_respond_with(200, body=expected))
with pact:
result = requests.get('https://jsonplaceholder.typicode.com/posts/1')
self.assertEqual(result.json(), expected)
Here I'm trying to hit JSONPlaceholder.
I'm using pytest
command to run the test.
But I'm getting the below error. I don't know what i'm missing.
self = <pact.pact.Pact object at 0x10cc8c8d0>
def verify(self):
"""
Have the mock service verify all interactions occurred.
Calls the mock service to verify that all interactions occurred as
expected, and has it write out the contracts to disk.
:raises AssertionError: When not all interactions are found.
"""
self._interactions = []
resp = requests.get(
self.uri + '/interactions/verification',
headers=self.HEADERS)
> assert resp.status_code == 200, resp.text
E AssertionError: Actual interactions do not match expected interactions for mock MockService.
E
E Missing requests:
E GET /posts/1
E
E See pact-mock-service.log for details.
venv/lib/python3.7/site-packages/pact/pact.py:209: AssertionError
I have tried pact.setup()
and pact.verify()
also but still I'm getting the same error. Can someone help me fix this?
And it doesn't create pactfile also. What are the things I have to setup?.
AssertionError: Actual interactions do not match expected interactions for mock MockService.
^ This error says that the pact mock didn't receive the interactions that were described in the Pact test.
E Missing requests:
E GET /posts/1
^ This part says that the mock didn't receive a GET
request for /posts/1
. If the mock server had received other requests (eg a POST
that it wasn't expecting), they would also be listed here.
So, we know that no requests hit the mock server during the test.
Reading the rest of the test class, we have:
with pact:
result = requests.get('https://jsonplaceholder.typicode.com/posts/1')
This shows that the test is hitting jsonplaceholder.typicode.com
instead of the mock set up during the test. So, the error is correct - to fix it we need to hit the mock server:
To fix your case, you'll need to contact the pact mock server instead:
with pact:
result = requests.get('https://localhost:1234/posts/1')
(Or whatever port you have configured Pact to listen on).
You can also get this directly from Pact:
with pact:
result = requests.get(pact.uri + '/posts/1')
You might find this diagram of a consumer test useful (taken from the How Pact Works section of the Pact documentation):
Your consumer code is the orange part, and the blue part is the mock provided by Pact.
During a Pact test, the consumer doesn't contact the actual provider, it only contacts the mock provider. The reverse is true for a provider verification - only the mock consumer contacts the real provider.
This means you don't need to spin up the consumer and provider together in order to test. This advantage is a major selling point of contract testing.