【问题标题】:Mock class using JEST in node在节点中使用 JEST 模拟类
【发布时间】:2020-08-21 21:18:19
【问题描述】:

所以,这实际上是我多次发生的事情,我一直不知道如何解决它。

我有这样的课

//myClass.js
const { get } = require('../models/myModel');

class MyClass {
    constructor(id) {
        this.id = id;
    }

    async getByID() {
        return get(this.id);
    }
}

还有一个控制器

//controller.js
module.exports = MyClass;

const MyClass = require('./MyClass.js');

module.exports = {
    getController: (req, res, next) => {
        try {
            const MyObject = new MyClass(1);
            const info = await MyObject.getByID();
            res.send(info)
        }
        catch (e) {
            next(e);
        }
    }
}

当我想进行 E2E 测试时,我需要模拟 getByID 以查看当它解决和拒绝时会发生什么。

那么,我如何模拟构造函数?我做了这样的事情

// myclass.spec.js


const MyClass = require('./MyClass.js');

jest.mock('./MyClass', () => jest.fn().mockImplementation(() => ({
  getByID: Promise.resolve({id: 1, name: 'John'}),
})));


describe('Testing MyClass', () => {
    it('Should return info', () => {
        const res = httpMocks.createResponse();
        const mReq = httpMocks.createRequest();
        const mNext = jest.fn();
        const mRes = mockResponse();
        await pipelineController(mReq, mRes, mNext);
        expect(mRes.send).toHaveBeenCalledWith(1);
        done();
    })
})

我知道此测试当前有效,但现在我无法更改 getByID 模拟值以查看当它拒绝承诺时会发生什么。

如果我尝试将它包含在测试中 (it) .... 它不会模拟任何东西... 我想要类似的东西


const MyClass = require('./MyClass.js');
const {pipelineController} = require('./controllers.js')

jest.mock('./MyClass', () => jest.fn().mockImplementation(() => ({
  getInfo: jest.fn(),
})));


describe('Testing MyClass', () => {
    it('Should return info', () => {
        ProcessService.getInfo.mockImplementation(() => Promise.resolve('the value i want'))
        const res = httpMocks.createResponse();
        const mReq = httpMocks.createRequest();
        const mNext = jest.fn();
        const mRes = mockResponse();
        await pipelineController(mReq, mRes, mNext);
        expect(mRes.send).toHaveBeenCalledWith(1);
        done();
    })
    it('Should return info', () => {
        ProcessService.getInfo.mockImplementation(() => Promise.reject('the reason i want'))
        const res = httpMocks.createResponse();
        const mReq = httpMocks.createRequest();
        const mNext = jest.fn();
        const mRes = mockResponse();
        await pipelineController(mReq, mRes, mNext);
        expect(mRes.send).toHaveBeenCalledWith(1);
        done();
    })

})

【问题讨论】:

  • 那个类没有多大意义。为什么 id 不是 method 的参数?
  • 这只是课程简介。我想学习的是如何用 jest 来模拟和改变值

标签: javascript node.js unit-testing jestjs


【解决方案1】:

由于getByID 在实例化后立即被调用,因此应在模拟类之外提供一个间谍以更改实现。

这可以通过 works in obscure and unspecified ways 的自动模拟类来完成,但可能适用于这种特定情况:

jest.mock('./MyClass.js')
const MyClass = require('./MyClass.js');
...
MyClass.prototype.getByID.mockResolvedValue({id: 1, name: 'John'});
// instantiate MyClass and call getByID

这可以通过在课堂外暴露一个间谍来完成:

const mockGetByID = jest.fn();
jest.mock('../../../services/ProcessService', () => jest.fn(() => (
  { getByID: mockGetByID }
)));
const MyClass = require('./MyClass.js');
...
mockGetByID.mockResolvedValue({id: 1, name: 'John'});
// instantiate MyClass and call getByID

【讨论】:

  • 嗨,埃斯图斯!谢谢您的答复。这目前不起作用。我收到参考错误ReferenceError: const mockGetByID = jest.fn();
  • 不清楚ReferenceError到底指的是什么,因为它应该清楚地提到麻烦的变量名,您在粘贴时是否修改了错误消息?更新。为了懒惰地访问 mockGetByID,可能应该将 mockReturnValue 替换为函数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-07-14
  • 2021-12-21
  • 2019-04-10
  • 1970-01-01
  • 2018-05-04
  • 1970-01-01
  • 2019-09-14
相关资源
最近更新 更多