如何在茉莉花测试中模拟导出的打字稿函数?

How do I mock an exported typescript function in a jasmine test?

我正在尝试在 Jasmine 测试中模拟从打字稿文件导出的函数。我希望以下内容模拟导入的 foo 和 return bar 规范中的值 1。

模拟似乎没有被调用,所以我显然遗漏了一些东西。我该如何修正这个例子?

demo.ts:

export function foo(input: any): any {
  return 2;
}

export function bar(input: any): any {
  return foo(input) + 2;
}

demo.ts.spec:

import * as demo from './demo';

describe('foo:', () => {
  it('returns 2', () => {
    const actual = demo.foo(1);
    expect(actual).toEqual(2);
  });
});

describe('bar:', () => {
  // let fooSpy;
  beforeEach(() => {
    spyOn(demo, 'foo' as any).and.returnValue(1); // 'as any' prevents compiler warning
  });

  it('verifies that foo was called', () => {
    const actual = demo.bar(1);
    expect(actual).toEqual(3); // mocked 1 + actual 2
    expect(demo.foo).toHaveBeenCalled();
  });
});

失败:

From this issue on Github: How are you expecting to use the spied on function in your actual implementation?

您的 bar 实现调用了 foo 实际实现 ,因为它直接引用了它。在另一个模块中导入时,会创建一个具有新引用的新对象:

// This creates a new object { foo: ..., bar: ... }
import * as demo from './demo';

这些引用仅存在于导入的模块中。当您调用 spyOn(demo, 'foo') 时,它就是正在使用的引用。你可能想在你的规范中尝试这个,测试通过的机会:

demo.foo();
expect(demo.foo).toHaveBeenCalled();

期望 bar 的真正实现调用模拟的 foo 是不可能的。相反,尝试将 bar 视为它有自己的 foo.

实现

Jeffery 的回答帮助我走上了正确的道路。

要附加间谍已附加到正确的参考文献中 foo 产品代码需要稍作更改。 foo() 应该被称为 this.foo()

下面的模式适用于测试(并且比我之前使用的复杂工作要干净得多)。

demo.ts:

export function foo(input: any): any {
  return 2;
}

export function bar(input: any): any {
  return this.foo(input) + 2;
}

demo.ts.spec:

import * as demo from './demo';

describe('foo:', () => {
  it('returns 2', () => {
    const actual = demo.foo(1);
    expect(actual).toEqual(2);
  });
});

describe('bar:', () => {
  // let fooSpy;
  beforeEach(() => {
    spyOn(demo, 'foo' as any).and.returnValue(1);
  });

  it('verifies that foo was called', () => {
    const actual = demo.bar(1);
    expect(actual).toEqual(3);
    expect(demo.foo).toHaveBeenCalled();
  });
});