Challenge: Using Mocks on Loosely Coupled Code

Apply your learnings in dependencies and mocks to complete a test challenge.


In this project, you’ll write unit tests that test the behavior of a class using mocks. An assessment rubric is provided to guide you on whether or not you have applied the principles taught in this chapter.

Self assessment rubric

I have… Emergent Satisfactory Excellent
Used the principles in the previous lessons Did not apply principles taught in the previous section Partially used principles taught from the previous section Used all the principles taught in the previous section
Used mocks Mocks not used Started to use mocks Mocks used extensively; used advanced features of a mocking framework

Application code summary

The application code below is an API. You can think of an API as software that constantly runs and listens to outside requests. When it receives a request, it performs CRUD operations on entries in a database. Therefore, APIs contain no front-end code. Each time you use an application like WhatsApp, send an instant message or check the weather on your phone, you’re using an API.

The API used in this project checks out customer orders for an ordering system. Given a debit/credit card, and delivery address information, the API checks out the order by updating some database.

When some piece of software talks to an API, its request hits something called a controller. The API used in this example has only one controller. In the code below, the controller is found in Project/Controllers/CartController.cs. Within the controller, the request hits a specific endpoint or action.

Our CartController controller has only one endpoint/action called CheckOut. This action must be supplied with a card and delivery address info before the checkout action can proceed with its task. If the card is charged, the controller returns the string charged. If the card is not charged, the controller returns the string not charged. There is an additional business rule in the controller, stated upfront, which says that if the number of special delivery requests exceeds a certain threshold, the cart checkout state is invalid and therefore cannot be charged. In practice, this could be because the commerce platform would like to limit special requests like packaging, adding gift cards, express delivery requests, etc. This business rule is contained in the IsCartCheckoutValid method. This method returns false if the number of special requests exceeds the special request limit (defined as 10 in the ICartService class). Otherwise, it returns true.

The controller has three dependencies. These dependencies and their descriptions are detailed below:

  • ICartService: This contains a list of items and their total checkout price.
  • IPaymentService: Using the Charge method, given a total checkout price and a card, charge the provided card with the amount provided.
  • IShipmentService: Using the Ship method, given an address and a list of items in the cart, ship the various items to the provided address.

These dependencies are called services because they service specific functionalities like shipping, payment, and cart storage. They are all located in the folder Project/Services. Don’t let the name services scare you!

These three dependencies use the following classes contained in Project/Services/Models.cs:

  • IAddressInfo: This data class contains address information.
  • ICard: This data class contains card information.
  • ICartItem: This data class contains item information.

The provided project contains no implementations for the ICartService, IPaymentService, and IShipmentService services. Only their interfaces are included.

Project requirement

Write test code that tests the CheckOut endpoint/action. To test this endpoint, note the following hints to help you in your solution:

  1. Test the case where a card is charged. This is the case where the string charged is returned.
  2. Test the case where a card is not charged. This is the case where the string not charged is returned.
  3. You are testing the controller that has three dependencies. Therefore, you will need to mock all three dependencies.
  4. Create a list of mocked cart items. For simplicity, let the list contain only one mocked item.
  5. Once all dependencies are mocked, create an instance of the controller with these mocked dependencies.
  6. The test code has been partially completed for you. You will need to complete the missing code and ensure all tests pass.

Get hands-on with 1200+ tech skills courses.