DEV Community

Mocking ES6 class methods with Jest!

Jack Caldwell on September 30, 2019

Prerequisites Before you get started with this tutorial, I'm going to presume that you already have a JavaScript project that you're wor...
Collapse
 
cannikin profile image
Rob Cameron

Any hints on how to restore the original functionality at the end of the test? When using this technique I'm seeing that the order the tests run in now matters—each test after this one ends up using that same mock. :(

Collapse
 
jackcaldwell profile image
Jack Caldwell

Looking at the mock function documentation - jestjs.io/docs/en/mock-function-api, you should be able to use mockFn.mockClear(), mockFn.mockReset(), or mockFn.mockRestore() depending on your needs. Hopefully this does what you need.

Collapse
 
09wattry profile image
Ryan

I have tried all of these functions and still the value is either the same or undefined. Any hints?

Thread Thread
 
mattarau profile image
Matt Arau

Have you tried afterEach(() => jest.resetAllMocks()); ?

Collapse
 
amitozdeol profile image
Amitoz Deol

If I change the getById method to

async getById(id) {
    const url = `http://localhost:3000/api/user/{id}`;
    const response = await fetch(url);
    return await response.json();
  }

the test will still pass. This is not expected behavior I want from test

Collapse
 
jackcaldwell profile image
Jack Caldwell

I'm not quite sure what you mean. In this example the 'ProductsManager' is the class being tested. The 'ProductsClient' is being mocked so we make assumptions about its behaviour in order to test the 'ProductsManager' in isolation. It's assumed that the 'ProductsClient' would be tested separately.

Collapse
 
09wattry profile image
Ryan • Edited

I'm not sure if directly modifying the prototype chain makes it impossible to reset/clear the mock.

An implementation a spying on the prototype chain seems to be working better for me i.e.

import { ProductsClient } from './ProductsClient';
import { ProductManager } from './ProductManager';

it('should return the product', async () => {
  const expectedProduct = {
    id: 1,
    name: 'football',
  };

   jest.spyOn(ProductsClient.prototype, 'getById')
     .mockReturnValue(expectedProduct);

  const productManager = new ProductManager();
  const result = await productManager.getProductToManage(1); 

  expect(result.name).toBe('football'); // It passes!
});

Enter fullscreen mode Exit fullscreen mode
Collapse
 
muhammedmoussa profile image
Moussa

i get ReferenceError: regeneratorRuntime is not defined

Collapse
 
max profile image
Maxime Lafarie • Edited

Very clever to mock the method through the prototype. I was struggling for hours, thank you!

Collapse
 
jab3z profile image
jab3z

Is there a reason why using

mockGetById.mockReturnValue(Promise.resolve(expectedProduct))

and not .resolves?

Collapse
 
carloszan profile image
Carlos

thank you! I'm wondering why it's not written on the jest docs that we have to override the method through prototype.