在 Jasmine 中模拟嵌套函数调用

问题描述

我目前正在尝试使用 Jasmine 测试我的打字稿功能

//AB.ts

export async function A() {
}
export async function B() {
    A();
}

我试图通过模拟 A 来对函数 B 进行单元测试。我想看看 A 是否被调用。这是我所拥有的:

//AB.spec.ts
import * as AB from './AB'

describe('AB has a function B that ',() => {
    it('calls A',async () => {
        let ASpy: jasmine.Spy;
        ASpy = spyOn(AB,'A').and.returnValue(Promise.resolve({}));
        await AB.B();
        expect(ASpy).toHaveBeenCalled();
    });
});

当我运行这个测试时,我被告知从来没有调用过 ASpy。但是经过进一步调查,我发现 A 函数确实被调用了。因此,似乎调用了 A 函数,但未触发我为该函数创建的模拟。我尝试在不同的文件中实现 A 函数并在 B 中调用它并在 AB.spec.ts 中模拟它;在这种情况下,测试通过,因为期望确定调用了 ASpy。 我不确定为什么将这两个函数放在同一个文件中会破坏测试,但将它们放在单独的文件中会通过测试。无论如何,我希望尽快收到某人的来信!我可以将这些函数放在单独的文件中,但我想在未来的项目中尽可能避免这样做。

解决方法

我看到你正在使用

Aspy = spyOn(AB,'A'); 

其中 AB 不是组件/类的对象,而只是您用来将这些全局函数导入到规范文件中的常量。

因此,问题实际上不在于您专门测试“异步”函数的任何代码,而在于您为没有类/组件对象的函数创建间谍的方式。您可能想要检查此线程并修改您的原始解决方案,以查看使用以下线程中的解决方案之一重新访问您的间谍是否能让您的原始测试正常运行..

Using Jasmine to spy on a function without an object

,

我能够找到一种方法来正确模拟 B 中的 A。只需要在我的函数调用中添加exports 关键字:

array1.map(el => {
array2.map(es => {
if(el.name === es.name){
/// here I am doing the logic,is there any optimized ways 
}
})})

这允许 B 的作用域看到 A 的定义,同时也允许 .spec 文件看到 A 正在尊重 A 的导出方法。