I found a new way because the suggested solutions don't work for me :(
So you can do it like this:
import * as FooFunctions from 'foo-functions';
spyOnProperty(FooFunctions, 'foo').and.returnValue(jasmine.createSpy());
If you want do callThrough
:
import * as FooFunctions from 'foo-functions';
const originalFn = FooFunctions.foo;
spyOnProperty(FooFunctions, 'foo').and.returnValue(
jasmine.createSpy().and.callFake(originalFn)
);
To make it more convenient, I made a helper. You can use it like this:
import * as FooFunctions from 'foo-functions';
spyOnFunction(FooFunctions, 'foo'); // to call through
spyOnFunction(FooFunctions, 'foo').and.callFake(...) // to call fake
spyOnFunction(FooFunctions, 'foo').and... // to do something else
Here is the helper code:
function spyOnFunction<T, K extends keyof T>(source: T, originalFnKey: K): jasmine.Spy {
const originalFn: T[K] = source[originalFnKey];
if (!isFunction(originalFn)) {
throw new Error('[spyOnFunction] spy target must be a function');
}
const spy: jasmine.Spy = jasmine.createSpy().and.callFake(originalFn);
spyOnProperty(source, originalFnKey).and.returnValue(spy);
return spy;
}
function isFunction(item: unknown): item is (...args: unknown[]) => unknown {
return typeof item === 'function';
}