expect(jest.fn()).toHaveBeenCalled() 即使已调用该函数也会失败

问题描述 投票:0回答:2

我正在尝试对返回承诺的函数进行单元测试。我在验证是否存在挑战 调用模拟函数。这就是我所做的。,

// codetotest.js
const { SomeModule, isSomething, isSomethingElse } = require("some-module");

exports.somefunction = (param1, param2)=> {
    const someModule = new SomeModule();

    someModule.someMethod("aaa", isSomething);
    someModule.someMethod("bbb", isSomethingElse);

    return (someModule.someOtherMethod(param1)
    .then(()=>{someModule.run(param2)}));
}

这是测试文件,测试说没有调用模拟函数,但我确实看到模拟函数中的控制台语句正在显示。

// codetotest.test.js
const { somefunction} = require("./codetotest.js");
const { SomeModule } = require("some-module");

jest.mock("some-module", () => {
    return {
        SomeModule: jest.fn().mockImplementation(() => {
            return {
                someMethod: jest.fn((param, fn) => { console.log("This prints!"); }),
                someOtherMethod: jest.fn((param) => { return Promise.resolve(() => { }) }),
                run: jest.fn((param) => { return Promise.resolve(() => { return []; }) })
            }
        })
    };
});

afterEach(() => {
    jest.resetAllMocks();
    jest.restoreAllMocks();
});

describe("Test codetotest.js", () => {
    it("somefunction() - success", async () => {
        const someModule = new SomeModule();

        let output = await somefunction("param1", "param2");

        expect(SomeModule).toHaveBeenCalled();
        expect(someModule.someMethod).toHaveBeenCalled(); // This fails

        await expect(someModule.someOtherMethod.mock.results[0]).resolves;
        expect(someModule.someOtherMethod).toHaveBeenCalled(); // This fails

        await expect(someModule.run.mocks.results[0]).resolves;
        expect(someModule.run).toHaveBeenCalled(); // This fails
    });
});

感谢任何帮助/指示。

谢谢你。

P.S:在 NodeJs 开发和单元测试方面我还是个初学者。

javascript node.js unit-testing jestjs
2个回答
4
投票

我花了相当多的时间在这上面,最后发现实例化的模拟类没有正确返回模拟方法。 这个答案给了我一个提示,告诉我哪里出了问题。

因此,我必须按如下方式更改我的测试文件。,

// codetotest.test.js
const { somefunction} = require("./codetotest.js");
const { SomeModule } = require("some-module");

jest.mock("some-module", function() {
    return {
        SomeModule: jest.fn().mockImplementation(function() { // Arrow function cannot be used as constructor
            // Because I was not using the 'this' operator, my constructor always returned empty
            this.someMethod = jest.fn((param, fn) => { console.log("This prints!"); });
            this.someOtherMethod = jest.fn((param) => { return Promise.resolve(() => { }) });
            this.run = jest.fn((param) => { return Promise.resolve(() => { return []; }) });
            return {
                someMethod: this,someMethod,
                someOtherMethod: this.someOtherMethod,
                run: this.run
            }
        })
    };
});

afterEach(() => {
    jest.restoreAllMocks();
});

describe("Test codetotest.js", () => {
    it("somefunction() - success", async () => {
        await somefunction("param1", "param2");

        expect(SomeModule).toHaveBeenCalled();
        expect(SomeModule.mock.instances[0].someMethod).toHaveBeenCalled(); // This works
        expect(SomeModule.mock.instances[0].someOtherMethod).toHaveBeenCalled(); // This works
        expect(someModule.mock.instances[0].run).toHaveBeenCalled(); // This works
    });
});

0
投票

我的情况有点不同,但它可以帮助一些来这里的人。代码是

jest.mock('@rollbar/react', () => ({
  useRollbar: jest.fn(() => {
    debug: jest.fn(),
    error: jest.fn(),
    info: jest.fn(),
    warning: jest.fn(),
  }),
}));

这段代码的问题是,每次我调用

useRollbar()
时,它都会实例化一个新对象,从而破坏方法实现的引用(因为在测试中我必须调用钩子来访问该对象以断言它已被调用)。 说了这么多,解决办法其实很简单

const rollbarMethods = {
  debug: jest.fn(),
  error: jest.fn(),
  info: jest.fn(),
  warning: jest.fn(),
};

jest.mock('@rollbar/react', () => ({
  useRollbar: jest.fn(() => rollbarMethods),
}));

这样模块返回的引用总是相同的

© www.soinside.com 2019 - 2024. All rights reserved.