Home Arrow Icon Knowledge base Arrow Icon Global Arrow Icon Can you provide an example of mocking an async function with Mocha in TypeScript


Can you provide an example of mocking an async function with Mocha in TypeScript


Sure, here's an example of mocking an asynchronous function with Mocha in TypeScript:

typescript
// myModule.ts
export class MyClass {
  async fetchData(): Promise<string> {
    return await this.makeApiCall();
  }

  private async makeApiCall(): Promise<string> {
    // Asynchronous API call implementation
    return 'data from API';
  }
}

// myModule.test.ts
import { MyClass } from './myModule';
import * as sinon from 'sinon';
import { expect } from 'chai';

describe('MyClass', () => {
  let myClassInstance: MyClass;
  let sandbox: sinon.SinonSandbox;

  beforeEach(() => {
    sandbox = sinon.createSandbox();
    myClassInstance = new MyClass();
  });

  afterEach(() => {
    sandbox.restore();
  });

  it('should fetch data successfully', async () => {
    // Mock the private makeApiCall method
    const mockedMakeApiCall = sandbox.stub(myClassInstance, 'makeApiCall').resolves('mocked data');

    const result = await myClassInstance.fetchData();
    expect(result).to.equal('mocked data');
    expect(mockedMakeApiCall).to.have.been.called;
  });

  it('should handle error in fetchData', async () => {
    // Mock the private makeApiCall method to reject with an error
    const mockedMakeApiCall = sandbox.stub(myClassInstance, 'makeApiCall').rejects(new Error('API error'));

    try {
      await myClassInstance.fetchData();
    } catch (error) {
      expect(error.message).to.equal('API error');
      expect(mockedMakeApiCall).to.have.been.called;
    }
  });
});

In this example, we have a `MyClass` that has an asynchronous `fetchData` method, which in turn calls a private `makeApiCall` method.

In the test suite, we use the following techniques to mock the asynchronous behavior:

1. Create a Sinon sandbox: We use `sinon.createSandbox()` to create a sandbox for managing the mocks.
2. Mock the private method: We use `sandbox.stub()` to create a stub for the `makeApiCall` method and replace its implementation with a mocked version.
3. Mock successful response: In the first test, we use the `resolves()` method to set the resolved value of the mocked `makeApiCall` method to `'mocked data'`.
4. Mock error response: In the second test, we use the `rejects()` method to set the rejected value of the mocked `makeApiCall` method to a new `Error` instance with the message `'API error'`.

In the tests, we then call the `fetchData` method and assert the expected behavior:

- In the first test, we expect the `fetchData` method to return the mocked data and verify that the `makeApiCall` method was called.
- In the second test, we expect the `fetchData` method to throw the mocked error and verify that the `makeApiCall` method was called.

Finally, we use the `afterEach` hook to restore the sandbox after each test to ensure a clean state for the next test.

By using these techniques, you can effectively mock asynchronous functions in TypeScript when using Mocha as your testing framework.