简体   繁体   中英

How do I completely mock an imported service class

I am looking to test my next API route which uses the micro framework (similar enough to express when using next-connect ).

I have a service:

export class UserService {
  constructor(...) {}

  async findUser({ email }: Pick<IUserModel, 'email'>) {
    ...
  }
}

My API endpoint:

import { NextApiRequest, NextApiResponse } from 'next';
import nc from 'next-connect';
import { UserService } from './UserService'; // Mock and prevent execution

const userService = new UserService();

export default nc().post(async (req: NextApiRequest, res: NextApiResponse) => {
  try {
    userService.findUser({ email: 'john.doe@example.com' });
    return res.status(200).send({ done: true });
  } catch (error: any) {
    return res.status(500).end(error.message);
  }
});

I would like to completely mock the import and prevent any dependent code from executing.

import { UserService } from './UserService';

For example if there is a console.log() in the UserService constructor it should not be run because the import is a completely mocked import.

Update:

I've attempted to use jest.mock but they didn't seem to actually mock my imports. I've added a console.log in the UserService constructor and it continues to be triggered when using jest.mock .

import signup from './signup';

jest.mock('./UserService');

describe('signup', () => {
  it('should complete the happy path', async () => {
    const req: IncomingMessage = {} as unknown as IncomingMessage;
    const res: ServerResponse = {
      end: jest.fn(),
    } as unknown as ServerResponse;

    const actual = await signup(req, res);
    expect(actual).toBe(...);
  });
});

If you mean mocking in a jest test then you can just use jest.mock('./userService'); or jest.spyOn(UserService, 'findUser') if you want to mock one method.

If you want a mock for a specific use case, you would create a mock service and conditionally import based on some flag.

Ex:

// UserService.js
export class UserService {
  constructor(...) {}

  async findUser({ email }: Pick<IUserModel, 'email'>) {
    // calls real API
  }
}


// UserService.mock.js
export class MockUserService {
  constructor(...) {}

  async findUser({ email }: Pick<IUserModel, 'email'>) {
    // calls fake API or just returns a promise or anything you want
  }
}

// Your Endpoint
import { NextApiRequest, NextApiResponse } from 'next';
import nc from 'next-connect';
import { UserService } from './UserService';
import { MockUserService } from './UserService.mock'; // Mock 

let userService;

if (someCondition) {
  userService = new UserService();
} else {
  userService = new MockUserService();
}
...

// The idea is you want to dynamically change what you're importing 
 
const Something = process.env.NODE_ENV === 'development' ?
  require('./FakeSomething') : require('./RealSomething');

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM