marchaos / jest-mock-extended

Type safe mocking extensions for Jest https://www.npmjs.com/package/jest-mock-extended
MIT License
845 stars 59 forks source link

deep mocks to deeply mock functions #16

Closed regevbr closed 3 years ago

regevbr commented 4 years ago

Currently, when creating a deep mock, there is no way to control the mocks of return values of first level mocked functions.

Essentially I want to be able to do:

interface A {
  y: () => Promise<string>;
}

interface B {
  x: () => Promise<A>;
}

const mocked = mockDeep<B>();
mocked.x.y.mockResolvedValue(`str`);
mrsufgi commented 4 years ago

much needed!

marchaos commented 3 years ago

You can do this with mockDeep() now.

guicostaarantes commented 1 year ago

Hey @marchaos, could you please provide an example of this? I can't see any on the docs.

For my use case I'm using mongodb. This is the function I'd like to test:

// getUser.ts
import { Db } from 'mongodb';

export async function getUser(db: Db, userId: string) {
  const user = await db.collection('users').findOne({ id: userId });

  if (!user) {
    throw 'User not found';
  }

  return user;
}

I'd like to be able to do something like this:

// getUser.test.ts
import { mockDeep } from 'jest-mock-extended';
import { Db } from 'mongodb';
import { getUser } from './getUser';

it('should throw error if user not found', async () => {
  const mockDb = mockDeep<Db>();

  // Alternative 1
  const mockUserCollection = mockDb.collection.calledWith('users');
  const mockFindOne = mockUserCollection.findOne.calledWith({ id: 'no-such-id' }).mockResolvedValue(null);

  // Alternative 2
  const mockFindOne = mockDb.collection.findOne.mockResolvedValue(null);

  expect(await getUser(mockDb, 'no-such-id')).toThrow('User not found');
  expect(mockFindOne).toHaveBeenCalledTimes(1);
});

Both alternatives are returning compile errors for me 😞 .

Thanks for the amazing lib, it's been great working with it 😄