When your shop calls another service, like a payment provider, your tests shouldn't call that service too. The real one may not be running, it charges real money, and you can't make it give the answer you want to test, like a declined card.
patch, from unittest.mock, swaps a function for a fake called a mock, but only inside a with block. Whatever you put in the mock's return_value is what the code gets back when it calls the function. Here a test fakes a shipping service on another route:
with patch("shipping.quote") as fake_quote:
fake_quote.return_value = {"price": 5}
response = self.client.get("/cart/shipping")
self.assertEqual(response.get_json()["shipping"], 5)
In this shop, paying an order calls payments.charge(amount, order_id) from the payments module. When the card is declined, the shop must answer 402 Payment Required, and the order must stay "pending". The check runs your tests on the shop and on two broken copies, then counts the calls that reached the real provider. When you're done, Run prints:
Your tests on the shop:
test_declined_card ... ok
test_new_order_is_pending ... ok
2 tests: OK
Your tests on a copy that marks the order paid before it asks the provider:
test_declined_card ... FAIL
AssertionError: 'paid' != 'pending'
test_new_order_is_pending ... ok
2 tests: 1 failed, so they caught this bug
Your tests on a copy that ignores what the provider answers:
test_declined_card ... FAIL
AssertionError: 201 != 402
test_new_order_is_pending ... ok
2 tests: 1 failed, so they caught this bug
Calls to the real payment provider: 0
Your task: write test_declined_card. Patch payments.charge so it answers {"error": "card_declined"}, pay order 1 with POST /orders/1/pay, check that the status is 402, then check that GET /orders/1 still shows the status "pending".
Assignment
Follow the Coding Tutorial to test a declined card, with a mock in place of the payment provider.
Hint
Set fake_charge.return_value before the POST, and keep the POST inside the with block, where payments.charge is the mock. The checks can go below the block.
Free plan: 30 tutor messages. PRO is unlimited.
