Hone logo
Hone
Problems

Jest Mocking: Creating a play Function

This challenge focuses on a common scenario in testing: mocking external dependencies. You'll create a play function that relies on an external audioPlayer service. Your task is to write a Jest test for this play function, specifically mocking the audioPlayer to control its behavior and verify that play interacts with it correctly. This skill is crucial for isolating your code under test and ensuring reliable, predictable tests.

Problem Description

You are tasked with creating a TypeScript function called play within a module. This play function is responsible for initiating playback of an audio file using a pre-existing audioPlayer service. The audioPlayer service has a method, let's call it playTrack, which takes a track name (a string) as an argument and starts playing that track.

Your primary goal is to write a Jest test suite for this play function. Within your tests, you need to mock the audioPlayer service. This means you will replace the actual audioPlayer implementation with a controlled, simulated version during the test. You should verify that your play function correctly calls the playTrack method of the mocked audioPlayer with the expected track name.

Key Requirements:

  1. Create a play function: This function should accept a trackName string as an argument.
  2. Dependency Injection: The play function should receive the audioPlayer service as a parameter, rather than importing it directly. This is a standard practice for making code more testable.
  3. Mock the audioPlayer: In your Jest tests, you will need to mock the audioPlayer object.
  4. Verify playTrack call: Assert that the playTrack method of the mocked audioPlayer is called exactly once with the correct trackName argument.

Expected Behavior:

When the play function is called with a track name and a mocked audioPlayer, the playTrack method of the audioPlayer should be invoked with that specific track name.

Edge Cases:

  • What happens if play is called with an empty string as trackName? (While the audioPlayer might handle this, your test should ensure play passes it through correctly).

Examples

Example 1:

Scenario: A standard call to play.

Input to play function: trackName = "Bohemian Rhapsody" mockAudioPlayer = { playTrack: jest.fn() }

Expected Jest Assertion: The playTrack method of mockAudioPlayer should be called with "Bohemian Rhapsody".

// Hypothetical structure of the play function (in your actual code)
// import { AudioPlayer } from './audioPlayer'; // You will NOT import directly in your test setup
// export function play(trackName: string, audioPlayer: AudioPlayer): void {
//   audioPlayer.playTrack(trackName);
// }

// In your test file:
describe('play', () => {
  it('should call playTrack on the audioPlayer with the correct track name', () => {
    const mockAudioPlayer = {
      playTrack: jest.fn(),
    };
    const trackToPlay = "Bohemian Rhapsody";

    // Assuming your play function is in a file named 'player.ts'
    // import { play } from './player';
    // For this challenge, imagine you have the 'play' function available.

    play(trackToPlay, mockAudioPlayer as any); // Cast to 'any' to satisfy type if AudioPlayer is defined elsewhere

    expect(mockAudioPlayer.playTrack).toHaveBeenCalledTimes(1);
    expect(mockAudioPlayer.playTrack).toHaveBeenCalledWith(trackToPlay);
  });
});

Example 2:

Scenario: Calling play with a different track.

Input to play function: trackName = "Stairway to Heaven" mockAudioPlayer = { playTrack: jest.fn() }

Expected Jest Assertion: The playTrack method of mockAudioPlayer should be called with "Stairway to Heaven".

Example 3: (Edge Case)

Scenario: Calling play with an empty track name.

Input to play function: trackName = "" mockAudioPlayer = { playTrack: jest.fn() }

Expected Jest Assertion: The playTrack method of mockAudioPlayer should be called with "".

Constraints

  • The play function must be written in TypeScript.
  • The testing framework must be Jest.
  • The audioPlayer service must be mocked in the tests.
  • Assume the play function is in a separate file (e.g., player.ts) and you are writing tests in a corresponding test file (e.g., player.test.ts).
  • The audioPlayer service has a method signature playTrack(trackName: string): void.

Notes

  • To effectively test play in isolation, you should pass the audioPlayer as an argument to the play function. This is known as dependency injection and is a key pattern for testability.
  • You will use jest.fn() to create mock functions for the audioPlayer's methods.
  • Familiarize yourself with Jest's assertion matchers like toHaveBeenCalledTimes and toHaveBeenCalledWith.
  • You might need to define a minimal AudioPlayer interface or type in your test file to satisfy TypeScript's type checking when passing the mock object.
  • Consider how you would organize your play function and its test for a clean, maintainable codebase.
Loading editor...
typescript