Chai-spies:expect().to.have.been.called() 在本地方法上失败

Chai-spies: expect().to.have.been.called() is failing on local methods

我正在尝试测试一些用 Typescript 编写的代码,但我的测试用例失败了。我稍微简化了代码以解决我的问题。我是 ts/js 的新手,所以很可能我只是遗漏了一些明显的东西..

我没有任何可以创建新对象的传统意义上的 classes。我只有两个打字稿文件,其中定义了函数。出于某种原因,当我期望调用的函数是我正在调用的函数的本地时,我的测试失败了。

下面是两个不同的例子及其结果。

我的调用函数 callFoo() 在我的 moduleUnderTest 文件中。当 callFoo() 在另一个文件中调用 foo() 时,我的测试用例将通过。

moduleUnderTest 文件(其中foo()来自帮助文件)

import { foo } from "path/to/helper/methods";

export function callFoo() {
    foo();
}

辅助方法

export function foo() {
    console.log("Foo was called");
}

这是我的测试代码

import { callFoo } from "path/to/module/under/test";
import * as helperMethods from "path/to/helper/methods";

chai.use(spies);
const expect = chai.expect;

suite("Testing Foo", () => {

    test("foo", async () => {
        const spy = chai.spy.on(helperMethods, "foo");
        await callFoo();
        expect(spy).to.have.been.called();
    });

});

输出(成功)

但是,如果我将 foo() 移动到同一个文件 moduleUnderTest 和 运行 相同的确切测试,它会失败。

export function callFoo() {
    foo();
}

export function foo() {
    console.log("local foo was called");
}

测试class

import { callFoo } from "path/to/module/under/test";
import *  as moduleUnderTest from "path/to/module/under/test";

chai.use(spies);
const expect = chai.expect;

suite("Testing Foo", () => {

    test("foo", async () => {
        const spy = chai.spy.on(moduleUnderTest, "foo");
        await callFoo();
        expect(spy).to.have.been.called();
    });

});

输出(失败)

所以你可以从输出中看到调用了方法

local foo was called

但是 expect().to.have.been.called() 失败了。这是为什么?我错过了什么?

我看到一篇描述我同样问题的文章。

这是文章https://medium.com/@DavideRama/mock-spy-exported-functions-within-a-single-module-in-jest-cdf2b61af642

这个问题与代码的编译方式有关。如果您不使用打字稿而只是使用 javascript,我强烈建议您阅读参考文章。

tdlr(打字稿解决方案);

  1. 将辅助函数(即 foo())移动到它自己的模块文件中

  1. 使用匿名函数:

来自https://github.com/facebook/jest/issues/936#issuecomment-532538300

不工作:

export function doSomething(a, b) {}

工作:

export const doSomething = function (a, b) {}

我还应该注意,我正在使用 mocha,我引用的 GitHub 问题提供了一些其他解决方案,如果使用 jest 可能更合适。就我而言,我选择从命名函数切换到匿名函数。