使用sequelize-mock 和 jest 模拟 findAll 和 findOne 的 Sequelize 模型

use*_*244 5 unit-testing node.js sequelize.js jestjs

对于我的用户的 CRUD,我正在使用sequelize-mockjest编写单元测试。模型模拟对我有用,但我的问题是关于模拟模型findAll(),并且findOne()在我的用户测试套件中调用它们都返回我在模拟模型中定义的排队结果。我期望如果我调用findAll(),我应该获取在排队结果中定义的所有数据,如果我调用,findOne()我应该只根据我传递的 id 从排队结果中获取一个数据。设置模拟模型autoQueryFallback: false对我不起作用。

这是一个代码片段:

在我的controllers/users.js

module.exports = {
    async list (req, res) {
        Users.findAndCountAll({
            limit: 10,
            offset: 0
        }).then(data => {
            console.log('Users >>> ', data);
        });
    },
    async view (req, res) {
        Users.findOne({
            where: { id: req.params.id }
        }).then(data => {
            console.log('User Data by ID >>> ', data);
        });
    }
};
Run Code Online (Sandbox Code Playgroud)

为了模拟我的用户模型,我必须创建一个__mocks__与模型相邻的目录(这就是 Jest 的工作原理)。所以,我的模型中有这个目录结构

> models/users.js
> models/__mocks__/users.js
Run Code Online (Sandbox Code Playgroud)
const Users = dbMock.define('users', {}, { autoQueryFallback: false });
Users.$queueResult([
    Users.build({
        id: 1,
        email: 'testActive@test.com',
        fullname : 'Test Active Users',
        status: 'active', 
    }),
    Users.build({
        id: 2,
        email: 'testDeleted@test.com',
        fullname: 'Test Deleted Users',
        status: 'deleted', 
    }),
]);
Run Code Online (Sandbox Code Playgroud)

模拟

我想使用模拟模型中的数据集来测试 users.list 和 users.view

jest.mock('../models/users');
describe('Testing use.list()', () => {
    it('UsersController.list() should return a status code 201 and all Users data in object array', async () => {
        await users.list(req, res);
        expect(res.json).toBeCalledWith(
            expect.objectContaining({
                data: expect.any(Object)
            })
        );
    });
    it('UsersController.view() should return a status code 201 and user data obj', async () => {
        //Passed req.params.id = 2
        await user.login(req, res);
        expect(res.status).toHaveBeenCalledWith(failureCode);
        expect(res.json).toBeCalledWith(
            expect.objectContaining({
                data: expect.any(Object)
            })
        );
    });
});
Run Code Online (Sandbox Code Playgroud)

sli*_*wp2 1

$useHandler(handler) -> QueryInterface可以做到这一点。我们可以根据query和来返回不同的查询结果queryOptions

\n

例如

\n

models/users.js

\n
// define user model\nmodule.exports = {};\n
Run Code Online (Sandbox Code Playgroud)\n

controller/users.js

\n
const Users = require(\'../models/users\');\n\nmodule.exports = {\n  async list(req, res) {\n    return Users.findAndCountAll({\n      limit: 10,\n      offset: 0,\n    }).then((data) => {\n      console.log(\'Users >>> \', data);\n      res.status(201).json({ data });\n    });\n  },\n  async view(req, res) {\n    return Users.findOne({\n      where: { id: req.params.id },\n    }).then((data) => {\n      console.log(\'User Data by ID >>> \', data);\n      res.status(201).json({ data });\n    });\n  },\n};\n
Run Code Online (Sandbox Code Playgroud)\n

controller/users.test.js

\n
const users = require(\'./users\');\n\njest.mock(\'../models/users\', () => {\n  const SequelizeMock = require(\'sequelize-mock\');\n  const dbMock = new SequelizeMock();\n  const UserMock = dbMock.define(\'user\');\n  UserMock.$queryInterface.$useHandler((query, queryOptions) => {\n    if (query === \'findAndCountAll\') {\n      return { count: 2, rows: [UserMock.build({ id: 1 }), UserMock.build({ id: 2 })] };\n    } else if (query === \'findOne\') {\n      return UserMock.build({ id: queryOptions[0].where.id });\n    }\n  });\n  return UserMock;\n});\n\ndescribe(\'Testing use.list()\', () => {\n  it(\'UsersController.list() should return a status code 201 and all Users data in object array\', async () => {\n    const req = {};\n    const res = { status: jest.fn().mockReturnThis(), json: jest.fn() };\n    await users.list(req, res);\n    expect(res.status).toHaveBeenCalledWith(201);\n    expect(res.json).toBeCalledWith(\n      expect.objectContaining({\n        data: expect.objectContaining({\n          count: 2,\n          rows: expect.arrayContaining([\n            expect.objectContaining({\n              id: expect.any(Number),\n              createdAt: expect.any(Date),\n              updatedAt: expect.any(Date),\n            }),\n          ]),\n        }),\n      }),\n    );\n  });\n  it(\'UsersController.view() should return a status code 201 and user data obj\', async () => {\n    const req = { params: { id: 2 } };\n    const res = { status: jest.fn().mockReturnThis(), json: jest.fn() };\n    await users.view(req, res);\n    expect(res.status).toHaveBeenCalledWith(201);\n    expect(res.json).toBeCalledWith(\n      expect.objectContaining({\n        data: expect.objectContaining({\n          id: 2,\n          createdAt: expect.any(Date),\n          updatedAt: expect.any(Date),\n        }),\n      }),\n    );\n  });\n});\n
Run Code Online (Sandbox Code Playgroud)\n

测试结果:

\n
 PASS  src/examples/stackoverflow/62455442/controller/users.test.js\n  Testing use.list()\n    \xe2\x9c\x93 UsersController.list() should return a status code 201 and all Users data in object array (12ms)\n    \xe2\x9c\x93 UsersController.view() should return a status code 201 and user data obj (12ms)\n\n  console.log src/examples/stackoverflow/62455442/controller/users.js:9\n    Users >>>  {\n      count: 2,\n      rows: [\n        fakeModelInstance {\n          options: [Object],\n          _values: [Object],\n          dataValues: [Object],\n          hasPrimaryKeys: true,\n          __validationErrors: []\n        },\n        fakeModelInstance {\n          options: [Object],\n          _values: [Object],\n          dataValues: [Object],\n          hasPrimaryKeys: true,\n          __validationErrors: []\n        }\n      ]\n    }\n\n  console.log src/examples/stackoverflow/62455442/controller/users.js:17\n    User Data by ID >>>  fakeModelInstance {\n      options: {\n        timestamps: true,\n        paranoid: undefined,\n        createdAt: undefined,\n        updatedAt: undefined,\n        deletedAt: undefined,\n        isNewRecord: true\n      },\n      _values: {\n        id: 2,\n        createdAt: 2023-03-21T06:19:42.373Z,\n        updatedAt: 2023-03-21T06:19:42.373Z\n      },\n      dataValues: {\n        id: 2,\n        createdAt: 2023-03-21T06:19:42.373Z,\n        updatedAt: 2023-03-21T06:19:42.373Z\n      },\n      hasPrimaryKeys: true,\n      __validationErrors: []\n    }\n\nTest Suites: 1 passed, 1 total\nTests:       2 passed, 2 total\nSnapshots:   0 total\nTime:        2.794s, estimated 3s\n
Run Code Online (Sandbox Code Playgroud)\n

软件包版本:

\n
"sequelize-mock": "^0.10.2",\n"jest": "^29.5.0",\n"sequelize": "^5.21.3",\n
Run Code Online (Sandbox Code Playgroud)\n