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:
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
.