Start learning free

LESSON 140 OF 173 · BACKEND: TESTS AND RUNNING IT

Fake the Other Service in C#

Practice

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 this lesson, Patch(name) swaps a function for a fake, often called a mock, but only inside a using block. Whatever you put in the fake's ReturnValue is what the code gets back when it calls the function. At the block's }, the real function is back. Here a test fakes a shipping service on another route:

HttpResponseMessage response;
using (var fakeQuote = Patch("shipping.quote")) {
    fakeQuote.ReturnValue = new { price = 5 };
    response = await client.GetAsync("/cart/shipping");
}
var cart = await response.Content.ReadFromJsonAsync<JsonElement>();
Assert.Equal(5, cart.GetProperty("shipping").GetInt32());

A variable declared inside a { } block is gone after its }, so response is declared above the block, and the checks below can still read it.

In this shop, paying an order calls payments.charge. 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:
  new order is pending ... ok
  declined card ... ok
  2 tests: OK
Your tests on a copy that marks the order paid before it asks the provider:
  new order is pending ... ok
  declined card ... FAIL
    Assert.Equal() Failure: Expected "pending", Actual "paid"
  2 tests: 1 failed, so they caught this bug
Your tests on a copy that ignores what the provider answers:
  new order is pending ... ok
  declined card ... FAIL
    Assert.Equal() Failure: Expected 402, Actual 201
  2 tests: 1 failed, so they caught this bug
Calls to the real payment provider: 0

Your task: write the test "declined card". Patch payments.charge so it answers new { 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 fake in place of the payment provider.


Hint
Set fakeCharge.ReturnValue before the POST, and keep the POST inside the using block, where payments.charge is the fake. Declare response above the block, so the checks below it can read it.


STEP 1 OF 9
    Ctrl + Enter to check

    Test Fake Service in C#

    Keep going with C#1,600+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free