admin管理员组

文章数量:1287675

I've been searching and trying for hours, but I still can't fix the issue. It keeps complaining:

Argument of type '{ commit: Mock; rollback: Mock; }' is not assignable to parameter of type 'never'.

(bcrypt.hash as jest.Mock).mockResolvedValue('hashedPassword');

I understand that TypeScript can't infer the return type of the mocked function. I've tried everything, including mockImplementation, but the errors won't go away.

Please help.

import { jest } from '@jest/globals';
import { AuthService } from '../../services/auth.service.js';
import bcrypt from 'bcrypt';
import models from '../../models/index.js';

jest.mock('bcrypt', () => ({
  hash: jest.fn(),
}));

jest.mock('../models/index.js', () => {
  const transaction = { commit: jest.fn(), rollback: jest.fn() };
  return {
    sequelize: {
      transaction: jest.fn().mockResolvedValue(transaction),
    },
    Users: {
      findOne: jest.fn(),
      create: jest.fn(),
    },
    Profiles: {
      create: jest.fn(),
    },
  };
});

describe('AuthService.register', () => {
  let authService: AuthService;

  beforeEach(() => {
    authService = new AuthService();
    jest.clearAllMocks();
  });

  it('should return error if user already exists', async () => {
    models.Users.findOne.mockResolvedValue({
      id: 1,
      email: '[email protected]',
    });

    const result = await authService.register('[email protected]', 'password');

    expect(result).toEqual({ success: false, message: 'User already exists' });
    expect(models.Users.findOne).toHaveBeenCalledWith({
      where: { email: '[email protected]' },
    });
  });

  it('should successfully register a new user', async () => {
    models.Users.findOne.mockResolvedValue(null);
    (bcrypt.hash as jest.Mock).mockResolvedValue('hashedPassword');
    models.Users.create.mockResolvedValue({ id: 1, email: '[email protected]' });
    models.Profiles.create.mockResolvedValue({ user_id: 1 });
    const transaction = { commit: jest.fn(), rollback: jest.fn() };
    models.sequelize.transaction.mockResolvedValueOnce(transaction);

    const result = await authService.register(' [email protected] ', 'password');

    expect(result).toEqual({
      success: true,
      message: 'Account created successfully',
    });
    expect(models.Users.create).toHaveBeenCalledWith(
      { email: '[email protected]', password: 'hashedPassword' },
      { transaction }
    );
    expect(models.Profiles.create).toHaveBeenCalledWith(
      { user_id: 1 },
      { transaction }
    );
    expect(transactionmit).toHaveBeenCalled();
  });

  it('should rollback transaction on error during creation', async () => {
    models.Users.findOne.mockResolvedValue(null);
    (bcrypt.hash as jest.Mock).mockResolvedValue('hashedPassword');
    const transaction = { commit: jest.fn(), rollback: jest.fn() };
    models.sequelize.transaction.mockResolvedValueOnce(transaction);
    models.Users.create.mockRejectedValue(new Error('DB error'));

    const result = await authService.register('[email protected]', 'password');

    expect(result).toEqual({ success: false, message: 'Registration failed' });
    expect(transaction.rollback).toHaveBeenCalled();
  });

  it('should handle error in outer try-catch', async () => {
    models.Users.findOne.mockRejectedValue(new Error('DB find error'));

    const result = await authService.register('[email protected]', 'password');

    expect(result).toEqual({
      success: false,
      message: 'Internal server error',
    });
  });
});

I've been searching and trying for hours, but I still can't fix the issue. It keeps complaining:

Argument of type '{ commit: Mock; rollback: Mock; }' is not assignable to parameter of type 'never'.

(bcrypt.hash as jest.Mock).mockResolvedValue('hashedPassword');

I understand that TypeScript can't infer the return type of the mocked function. I've tried everything, including mockImplementation, but the errors won't go away.

Please help.

import { jest } from '@jest/globals';
import { AuthService } from '../../services/auth.service.js';
import bcrypt from 'bcrypt';
import models from '../../models/index.js';

jest.mock('bcrypt', () => ({
  hash: jest.fn(),
}));

jest.mock('../models/index.js', () => {
  const transaction = { commit: jest.fn(), rollback: jest.fn() };
  return {
    sequelize: {
      transaction: jest.fn().mockResolvedValue(transaction),
    },
    Users: {
      findOne: jest.fn(),
      create: jest.fn(),
    },
    Profiles: {
      create: jest.fn(),
    },
  };
});

describe('AuthService.register', () => {
  let authService: AuthService;

  beforeEach(() => {
    authService = new AuthService();
    jest.clearAllMocks();
  });

  it('should return error if user already exists', async () => {
    models.Users.findOne.mockResolvedValue({
      id: 1,
      email: '[email protected]',
    });

    const result = await authService.register('[email protected]', 'password');

    expect(result).toEqual({ success: false, message: 'User already exists' });
    expect(models.Users.findOne).toHaveBeenCalledWith({
      where: { email: '[email protected]' },
    });
  });

  it('should successfully register a new user', async () => {
    models.Users.findOne.mockResolvedValue(null);
    (bcrypt.hash as jest.Mock).mockResolvedValue('hashedPassword');
    models.Users.create.mockResolvedValue({ id: 1, email: '[email protected]' });
    models.Profiles.create.mockResolvedValue({ user_id: 1 });
    const transaction = { commit: jest.fn(), rollback: jest.fn() };
    models.sequelize.transaction.mockResolvedValueOnce(transaction);

    const result = await authService.register(' [email protected] ', 'password');

    expect(result).toEqual({
      success: true,
      message: 'Account created successfully',
    });
    expect(models.Users.create).toHaveBeenCalledWith(
      { email: '[email protected]', password: 'hashedPassword' },
      { transaction }
    );
    expect(models.Profiles.create).toHaveBeenCalledWith(
      { user_id: 1 },
      { transaction }
    );
    expect(transactionmit).toHaveBeenCalled();
  });

  it('should rollback transaction on error during creation', async () => {
    models.Users.findOne.mockResolvedValue(null);
    (bcrypt.hash as jest.Mock).mockResolvedValue('hashedPassword');
    const transaction = { commit: jest.fn(), rollback: jest.fn() };
    models.sequelize.transaction.mockResolvedValueOnce(transaction);
    models.Users.create.mockRejectedValue(new Error('DB error'));

    const result = await authService.register('[email protected]', 'password');

    expect(result).toEqual({ success: false, message: 'Registration failed' });
    expect(transaction.rollback).toHaveBeenCalled();
  });

  it('should handle error in outer try-catch', async () => {
    models.Users.findOne.mockRejectedValue(new Error('DB find error'));

    const result = await authService.register('[email protected]', 'password');

    expect(result).toEqual({
      success: false,
      message: 'Internal server error',
    });
  });
});
Share Improve this question edited Feb 23 at 21:09 Louis Tran asked Feb 23 at 2:57 Louis TranLouis Tran 1,1662 gold badges26 silver badges46 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 1

I have faced similar issues with jest and ts, and one of the below 2 ways work for me

  1. using mockImplementation rather than mockResolvedValue everywhere for transaction mock, for you code you can do it like:
jest.mock('../../models/index.js', () => {
  return {
    sequelize: {
      transaction: jest.fn().mockImplementation(() =>
        Promise.resolve({
          commit: jest.fn(),
          rollback: jest.fn(),
        })
      ),
    },
    Users: {
      findOne: jest.fn(),
      create: jest.fn(),
    },
    Profiles: {
      create: jest.fn(),
    },
  };
});
  1. or you can forcefully type the transaction as a mock:

for this firstly import the file as a mock:

import models from '../../models/index.js';
jest.mock('../../models/index.js');

secondly inside the beforeEach function you can write:

(models.sequelize.transaction as jest.Mock).mockResolvedValue({
  commit: jest.fn(),
  rollback: jest.fn(),
});

本文标签: javascriptJest Mock Function cannot recognize return typesStack Overflow