TypeError: 在模拟 sequelize 模型时,User.findOne 不是一个函数。

huangapple go评论65阅读模式
英文:

TypeError: User.findOne is not a function when mocking sequelize model in vitest

问题

I'm here to provide the Chinese translation of the text you provided:

我正在尝试运行一些 Jest 测试,针对使用 Sequelize ORM 的 auth.service.js 模块。然而,当我运行这些测试时,我遇到了以下错误:

FAIL  tests/modules/auth/auth.service.test.js > AuthService > login > should login user and return token
TypeError: User.findOne is not a function

以下是 AuthService 的代码:

const User = require('../../db/models/User');
const AuthService = {
  doLogin: async (requestBody) => {
    const { email, password } = requestBody;
    const user = await User.findOne({ where: { email } });
    // 其余代码
  }
}

module.exports = AuthService;

这是测试代码:

import { describe, it, expect, vi, afterEach } from 'vitest';
import bcrypt from 'bcryptjs';
import SequelizeMock from 'sequelize-mock';

const { faker } = require('@faker-js/faker');

const AuthService = require('../../../src/modules/auth/auth.service');
const JwtService = require('../../../src/modules/auth/jwt.service');

vi.mock('../../../src/db/models/User', async () => {
  const dbMock = new SequelizeMock();
  const fakeUser = {
    id: 1,
    phone: faker.phone.phoneNumber('##########'),
    password: faker.internet.password(8),
  };
  const UserMock = dbMock.define('User', fakeUser);
  return UserMock;
});

describe('AuthService', () => {
  afterEach(() => {
    vi.restoreAllMocks();
  });

  describe('login', () => {
    it('should login user and return token', async () => {
      // 安排
      const requestBody = {
        phone: faker.phone.phoneNumber('##########'),
        password: faker.internet.password(8),
      };
      const fakeUser = {
        id: faker.datatype.uuid(),
        role: faker.datatype.string(4),
      };
      const fakeAccessToken = 'fake-access-token';
      vi.spyOn(bcrypt, 'compareSync').mockImplementation(() => true);
      vi.spyOn(JwtService, 'generateJWT').mockResolvedValue(fakeAccessToken);

      const expected = {
        ...fakeUser,
        accessToken: fakeAccessToken,
      };

      // 执行
      const result = await AuthService.doLogin(requestBody);

      // 断言
      expect(result).toEqual(expected);
    });
  });
});

我已为您提供了翻译的文本,如果您有任何其他问题,请随时提出。

英文:

I'm trying to run some Jest tests for the auth.service.js module, which uses Sequelize ORM. However, when I run the tests, I'm getting the following error:

FAIL  tests/modules/auth/auth.service.test.js > AuthService > login > should login user and return token
TypeError: User.findOne is not a function

Here is the code for AuthService

const User = require('../../db/models/User');
const AuthService =  {
doLogin: async (requestBody) => {
const { email, password } = requestBody;
const user = await User.findOne({ where: { email } });
// rest of the code
}
}
module.exports = AuthService;

And here is the test code,

import { describe, it, expect, vi, afterEach } from 'vitest';
import bcrypt from 'bcryptjs';
import SequelizeMock from 'sequelize-mock';
const { faker } = require('@faker-js/faker');
const AuthService = require('../../../src/modules/auth/auth.service');
const JwtService = require('../../../src/modules/auth/jwt.service');
vi.mock('../../../src/db/models/User', async () => {
const dbMock = new SequelizeMock();
const fakeUser = {
id: 1,
phone: faker.phone.phoneNumber('##########'),
password: faker.internet.password(8),
};
const UserMock = dbMock.define('User', fakeUser);
return UserMock;
});
describe('AuthService', () => {
afterEach(() => {
vi.restoreAllMocks();
});
describe('login', () => {
it('should login user and return token', async () => {
// Arrange
const requestBody = {
phone: faker.phone.phoneNumber('##########'),
password: faker.internet.password(8),
};
const fakeUser = {
id: faker.datatype.uuid(),
role: faker.datatype.string(4),
};
const fakeAccessToken = 'fake-access-token';
vi.spyOn(bcrypt, 'compareSync').mockImplementation(() => true);
vi.spyOn(JwtService, 'generateJWT').mockResolvedValue(fakeAccessToken);
const expected = {
...fakeUser,
accessToken: fakeAccessToken,
};
// Act
const result = await AuthService.doLogin(requestBody);
// Assert
expect(result).toEqual(expected);
});
});
});

I also tried the below answers, but none of them work:

https://stackoverflow.com/questions/62455442/sequelize-model-mocking-findall-and-findone-using-sequelize-mock-and-jest

https://stackoverflow.com/questions/66698322/mock-sequelize-with-jest-and-sequelize-mock

答案1

得分: 0

vitest 给我的错误信息不正确。在 vi.mock() 内部,我们无法访问外部范围的变量。

当我将它更改为 jest 后,我遇到了这个错误。现在,我已经将测试运行程序从 vitest 更改为 jest,它正在工作。我还删除了 sequelize-mock 依赖项,因为目前我不需要它。

const bcrypt = require('bcryptjs');

const { faker } = require('@faker-js/faker');

const AuthService = require('../../../src/modules/auth/auth.service');
const JwtService = require('../../../src/modules/auth/jwt.service');

jest.mock('../../../src/db/models/User', () => {
  const fakeUser = {
    id: 'fake-id',
    role: 'fake-role'
  };
  const User = {
    findOne: jest.fn().mockResolvedValue(fakeUser)
  };
  return User;
});

describe('AuthService', () => {
  describe('login', () => {
    it('should login user and return token', async () => {
      // Arrange
      const requestBody = {
        phone: faker.phone.phoneNumber('##########'),
        password: faker.internet.password(8),
      };
      const resolvedFakeUser = {
        userId: 'fake-id',
        role: 'fake-role',
      };
      const fakeAccessToken = 'fake-access-token';
      jest.spyOn(bcrypt, 'compareSync').mockImplementation(() => true);
      jest.spyOn(JwtService, 'generateJWT').mockResolvedValue(fakeAccessToken);

      const expected = {
        ...fakeUser,
        accessToken: fakeAccessToken,
      };

      // Act
      const result = await AuthService.doLogin(requestBody);

      // Assert
      expect(result).toEqual(expected);
    });
  });
});
英文:

vitest was not giving me proper errors. Inside vi.mock() we can't access outside scoped variables.

I got this error when I changed it to jest. Now, I have changed my test runner from vitest to jest, and it's working. I also removed sequelize-mock dependency as I don't need this for my use case as of now.

const bcrypt = require('bcryptjs');
const { faker } = require('@faker-js/faker');
const AuthService = require('../../../src/modules/auth/auth.service');
const JwtService = require('../../../src/modules/auth/jwt.service');
jest.mock('../../../src/db/models/User', () => {
const fakeUser = {
id: 'fake-id',
role: 'fake-role'
};
const User = {
findOne: jest.fn().mockResolvedValue(fakeUser)
};
return User;
});
describe('AuthService', () => {
describe('login', () => {
it('should login user and return token', async () => {
// Arrange
const requestBody = {
phone: faker.phone.phoneNumber('##########'),
password: faker.internet.password(8),
};
const resolvedFakeUser = {
userId: 'fake-id',
role: 'fake-role',
};
const fakeAccessToken = 'fake-access-token';
jest.spyOn(bcrypt, 'compareSync').mockImplementation(() => true);
jest.spyOn(JwtService, 'generateJWT').mockResolvedValue(fakeAccessToken);
const expected = {
...fakeUser,
accessToken: fakeAccessToken,
};
// Act
const result = await AuthService.doLogin(requestBody);
// Assert
expect(result).toEqual(expected);
});
});
});

huangapple
  • 本文由 发表于 2023年5月15日 12:27:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/76250881.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定