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

这一生的挚爱 提交于 2019-12-11 02:26:36

问题


I'm trying to mock a function exported from a typescript file in a Jasmine test. I expect the following to mock the imported foo and return the value 1 in the spec for bar.

The mock appears to be uncalled, so I'm clearly missing something. How can I fix this example?

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();
  });
});

Failures:

  • Expected 4 to equal 3.
  • Expected spy foo to have been called.

回答1:


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

Your bar implementation calls the actual implementation of foo, because it has a direct reference to it. When importing in another module, a new object, with new references, is created:

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

These references exist only in the module of the import. When you call spyOn(demo, 'foo') it's that reference that is being used. You might want to try this in your spec, chances are the test passes:

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

Expecting the real implementation of bar to call a mocked foo is not really possible. Instead try to treat bar as if it had its own implementation of foo.




回答2:


Jeffery's answer helped get me on the right track.

To attach the spy is attached to the right reference for foo the product code needs to have a small change. foo() should be called as this.foo()

The below pattern works for testing (and is a lot cleaner than the convoluted work around I was using previously).

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();
  });
});


来源:https://stackoverflow.com/questions/49538472/how-do-i-mock-an-exported-typescript-function-in-a-jasmine-test

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!