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.
In Go, a function is a value you can keep in a variable. When the shop calls the other service through a variable, a test can store a fake function in it: whatever the fake returns is what the shop gets back. Keep the real function first and put it back afterwards, so later code gets the real one again. Here a test fakes a shipping service on another route:
realQuote := shipping.Quote
shipping.Quote = func(weight int) map[string]any {
return map[string]any{"price": 5}
}
response, _ := http.Get(s.server.URL + "/cart/shipping")
shipping.Quote = realQuote
In this shop, paying an order calls payments.Charge(amount, orderID), a func(amount int, orderID int) map[string]any. 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:
TestDeclinedCard ... ok
TestNewOrderIsPending ... ok
2 tests: OK
Your tests on a copy that marks the order paid before it asks the provider:
TestDeclinedCard ... FAIL
Not equal: expected "pending", actual "paid"
TestNewOrderIsPending ... ok
2 tests: 1 failed, so they caught this bug
Your tests on a copy that ignores what the provider answers:
TestDeclinedCard ... FAIL
Not equal: expected 402, actual 201
TestNewOrderIsPending ... ok
2 tests: 1 failed, so they caught this bug
Calls to the real payment provider: 0
Your task: write the method TestDeclinedCard. Keep the real payments.Charge in realCharge, set payments.Charge to a fake that returns map[string]any{"error": "card_declined"}, pay order 1 with POST /orders/1/pay, put the real function back, 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 fake function in place of the payment provider.
Hint
The fake must have the same type as payments.Charge: it takes amount and orderID and returns a map[string]any, even if it never uses them. Make the POST while the fake is in place; the checks can come after you put realCharge back.
Free plan: 30 tutor messages. PRO is unlimited.
