DEV Community

Cover image for How to mock an imported Typescript class with Jest

How to mock an imported Typescript class with Jest

Abou Kone on April 02, 2020

Sooner or later in your unit tests you will run into an issue where you need to import a class into your test and mock it, to keep up with good tes...
Collapse
 
komyg profile image
Felipe Armoni • Edited

Merci pour m'aider avec un test difficile d'Electron. Maintenant je peu faire un mock de l'object BrowserWindow et tester le classes de niveu plus bas. Il-y-a un example:

import { MyWindow } from './my-window';
import { mocked } from 'ts-jest/utils';
import { BrowserWindow } from 'electron';

jest.mock('electron', () => ({
  BrowserWindow: jest.fn(),
}));

describe('My Window Test', () => {
  it('should show the window', () => {
    const windowShow = jest.fn();

    const windowMock: any = mocked(BrowserWindow, true);
    windowMock.mockImplementation(() => ({
      show: windowShow,
      loadURL: jest.fn(),
    }));

    const myWindow = new MyWindow();
    myWindow.openWindow();
    expect(windowShow).toHaveBeenCalled();
  });
});
Enter fullscreen mode Exit fullscreen mode
Collapse
 
jakemonton profile image
Jake Monton

how do you call the playSoundFile method?

Collapse
 
bmitchinson profile image
Ben Mitchinson • Edited

What took me forever to realize is the jest.mock has to be done above the describe block.

additionally, instead of using this library, I now use

const mockMyClass = MyClass as jest.MockedClass<
            typeof MyClass
        >;

Enter fullscreen mode Exit fullscreen mode

Update: I now use the following method: dev.to/bmitchinson/mocking-classes...

Collapse
 
soullivaneuh profile image
Sullivan SENECHAL

I try to mock a FeathersJS service class with your article example without any success.

I cannot figure out how to check class methods calls.

I ended up an another way with this:

import { mocked } from 'ts-jest/utils';
import app from '../../src/app';
import { Notifications } from '../../src/services/notifications/notifications.class';
import { NotificationsData } from '../../src/types';

jest.mock('../../src/services/notifications/notifications.class');
const mockNotificationsService = mocked(Notifications, true);
const mockNotificationsCreate = mocked(mockNotificationsService.mock.instances[0].create)
mockNotificationsCreate.mockImplementation(() => Promise.resolve({} as NotificationsData));

beforeEach(() => {
  // Clear registered calls from older tests.
  mockNotificationsCreate.mockClear();
})

describe('\'foo\' service', () => {
  it(
    'mock implement test',
    () => {
      return app.service('foo').create({ foo: 'bar' })
        .then(() => {
          expect(mockNotificationsCreate).toBeCalledTimes(1);
          expect(mockNotificationsCreate).toHaveBeenNthCalledWith(1, {
            applicationSlug: 'kidways',
            body: 'body',
            title: 'title',
            userIds: [
              'user1'
            ]
          }, {});
        })
    },
  );

  it(
    'mock implement test second',
    () => {
      return app.service('foo').create({ foo: 42 })
        .then(() => {
          expect(mockNotificationsCreate).toBeCalledTimes(2);
          expect(mockNotificationsCreate).toHaveBeenNthCalledWith(1, {
            applicationSlug: 'slug',
            body: 'body',
            title: 'title',
            userIds: [
              'user1'
            ]
          }, {});
          expect(mockNotificationsCreate).toHaveBeenNthCalledWith(2, {
            applicationSlug: 'slug',
            body: '42',
            title: 'title',
            userIds: [
              'user1'
            ]
          }, {});
        })
    },
  );
});
Enter fullscreen mode Exit fullscreen mode

This works but the implements looks wrong. I have to first mock the whole class with jest.mock then mock one of the method while storing it on a variable for test check.

Is it the way to go? Will you do the same way?

Thanks!

Collapse
 
dorianneto profile image
Dorian Neto

mocked() function from ts-jest saved my life! Thank you for the tip :)

Collapse
 
devakone profile image
Abou Kone

You're welcome!

Collapse
 
ultrarunner profile image
ultrarunner

Merci Beaucoup.

Collapse
 
devakone profile image
Abou Kone

De rien!

Collapse
 
emmytobs profile image
Emmanuel Otobo

I got an error saying X.mockClear is not a function (X is the class I want to mock). I can't find anything wrong with my setup. Could you help suggest what I can do to resolve it. Thanks

Collapse
 
jotafeldmann profile image
Jota Feldmann

@devakone thanks a lot man! 🚀

Collapse
 
devbirgit profile image
Birgit Pohl 🏡

Thanks. It looks pretty easy.
I was wondering when a mockedClass is re-used throughout the project, how this may look like. jest.mock() does not return anything, does it?

Collapse
 
dylajwright profile image
Dylan

Anyone looking for the link to the ts-jest mocked document, it is this kulshekhar.github.io/ts-jest/docs/...

Github and Kulshekhar have been inverted to find the docs.

Collapse
 
dylajwright profile image
Dylan • Edited

I also found value in understanding what the Mock Implementation is doing. In this link, jonathancreamer.com/testing-typesc..., explains what that is before mockImplementation was created. An assumption on creation regardless it explains that well which makes this article very fluent.