Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JestJS: How to get different promise results of a mocked function and test for thrown error?

I need to test a function (example()), which uses another one (validateDataset). As I only want to test the example() function I mock the validateDataset().

Of course each test needs a different result of the mocked function. But how do I set different promise results for the mocked function? In my attempt shown below the mocked function always return the same value.

So in this example I cannot test for the thrown error.

functions.js

import { validateDataset } from './helper/validation'

export async function example (id) {
  const { docElement } = await validateDataset(id)
  if (!docElement) throw Error('Missing content')
  return docElement
}

functions.test.js

import { example } from './functions'

jest.mock('./helper/validation', () => ({
  validateDataset: jest.fn(() => Promise.resolve({
    docMain: {},
    docElement: {
      data: 'result'
    }
  }))
}))

describe('example()', () => {
  test('should return object', async () => {
    const result = await example('123')
    expect(result.data).toBe('result')
  })
  test('should throw error', async () => {
    const result = await example('123')
    // How to get different result (`null`) in this test
    // How to test for the thrown error?
  })
})
like image 215
user3142695 Avatar asked Dec 30 '17 13:12

user3142695


1 Answers

What's great about Jest mocking, is that you can mock-out the whole module, and by requiring its default or named exports, you still get a mock, which you can implement and reimplement however and wherever you like.

I've posted a sample implementation of the test that expects validateDataset call to fail. I also left some comments for brevity.

import { example } from './example';
import { validateDataset } from './helper/validation';

// Declare export of './helper/validation' as a Mock Function.
// It marks all named exports inside as Mock Functions too.
jest.mock('./helper/validation');

test('example() should return object', async () => {
  // Because `validateDataset` is already mocked, we can provide
  // an implementation. For this test we'd like it to be original one.
  validateDataset.mockImplementation(() => {
    // `jest.requireActual` calls unmocked module
    return jest.requireActual('./helper/validation').validateDataset();
  });
  const result = await example('123');
  expect(result.data).toBe('result');
});

test('example() should throw error', async () => {
  // Worth to make sure our async assertions are actually made
  expect.assertions(1);
  // We can adjust the implementation of `validateDataset` however we like,
  // because it's a Mock Function. So we return a null `docElement`
  validateDataset.mockImplementation(() => ({ docElement: null }));
  try {
    await example('123');
  } catch (error) {
    expect(error.message).toEqual('Missing content');
  }
});

Hope that clears things out.

like image 186
Michał Pierzchała Avatar answered Nov 14 '22 03:11

Michał Pierzchała