Hone logo
Hone
Problems

Spying on a Method in Jest: Mocking and Verification

This challenge focuses on using Jest's mocking capabilities to spy on a method within an object. Spying allows you to track how many times a method is called, what arguments it receives, and even replace its implementation with a mock function, all while maintaining the original method's existence. This is crucial for isolating units of code during testing and verifying interactions between components.

Problem Description

You are given a module calculator.ts containing a Calculator class with a calculateDiscountedPrice method. This method takes a price and a discount percentage as input and returns the discounted price. You need to write a Jest test that spies on the calculateDiscountedPrice method of a Calculator instance.

The test should:

  1. Create an instance of the Calculator class.
  2. Spy on the calculateDiscountedPrice method of the instance.
  3. Call a separate method, applyDiscount, which internally calls calculateDiscountedPrice.
  4. Verify that calculateDiscountedPrice was called exactly once.
  5. Verify that calculateDiscountedPrice was called with the correct arguments (price: 100, discount: 10).

Examples

Example 1:

Input: calculator.ts (see below), applyDiscount.ts (see below), and a Jest test file.
Output: A Jest test that passes, verifying the spy on calculateDiscountedPrice.
Explanation: The test creates a Calculator instance, spies on calculateDiscountedPrice, calls applyDiscount, and then asserts that calculateDiscountedPrice was called once with the expected arguments.

Example 2: (Edge Case - No Discount)

Input: calculator.ts (see below), applyDiscount.ts (see below), and a Jest test file.
Output: A Jest test that passes, verifying the spy on calculateDiscountedPrice.
Explanation: Even if the discount is 0, the spy should still be called once with the correct arguments.

Constraints

  • The solution must be written in TypeScript.
  • The solution must use Jest's spyOn function.
  • The solution must verify both the call count and the arguments passed to the spied method.
  • The solution must not modify the original calculateDiscountedPrice method's implementation unless explicitly required for the test setup.

Notes

  • Consider using mockImplementation if you need to control the return value of the spied method during the test. However, for this problem, simply verifying the call is sufficient.
  • Pay close attention to the order of operations: create the instance, spy on the method, call the method that uses the spied method, and then verify the spy.
  • The applyDiscount method is provided to encapsulate the call to calculateDiscountedPrice, making the test more focused on spying.

Files to be provided (for context - you don't need to create these, just understand their purpose):

calculator.ts:

export class Calculator {
  calculateDiscountedPrice(price: number, discount: number): number {
    return price - (price * discount / 100);
  }
}

applyDiscount.ts:

import { Calculator } from './calculator';

export function applyDiscount(calculator: Calculator, price: number, discount: number): number {
  return calculator.calculateDiscountedPrice(price, discount);
}
Loading editor...
typescript