Proper mocking pattern for Jasmine based unit tests #4252
-
Unit testing in Jasmine and Karma (standard Angular setup), is proving to be a challenge. I created a repo to simplify that challenge as much as possible. All of the relevant code is here: https://github.com/kensodemann/test-cap-3/tree/main/src/app/core
export class WebFakeStorage {
async set(opts: { key: string; value: string }): Promise<void> {
console.log('set called with ', opts);
}
async get(opts: { key: string }): Promise<{ value: string }> {
return { value: 'monkey' };
}
} import { WebFakeStorage } from './web-fake-storage';
const FakeStorage = new WebFakeStorage();
export { FakeStorage };
callFakeStorage(): Promise<{ value: string }> {
return FakeStorage.get({ key: 'plastic' });
}
callCapStorage(): Promise<{ value: string }> {
return Storage.get({ key: 'flaming' });
} The fake-storage tests work great. The first one spies on the FakeStorage.get and calls it directly (not typical for a test, obviously, but more or less just proving the sypOn call is working). The second test is more typical in that it calls the service after setting up the spy. So far, so good... But then we move on to the Storage plugin, and even the simple case does not work. Line 37 results in {value: null} basically indicating that the real Storage.get was called and not the spy. Uncommenting 38 & 39 results in an error about expecting a spy and getting a function. Those two items put together indicate that the spyOn on line 36 did not really create a spy or something, which is really odd, though I am guessing is has to do with some of the "magic" we are trying to do in the Basically, though, if we could get the same mocking paradigm to work on a Capacitor plugin as works on a standard JavaScript object that would be ideal. If we cannot, then we need to document what that pattern should be. If my test is missing something that would make this work, then we probably just need to document that. Working (std JS Object) import { FakeStorage } from './fake-storage';
...
it('can be spied upon', async () => {
spyOn(FakeStorage, 'get').and.returnValue(Promise.resolve({ value: 'abides' }));
expect(await FakeStorage.get({ key: 'dude' })).toEqual({ value: 'abides' });
expect(FakeStorage.get).toHaveBeenCalledTimes(1);
expect(FakeStorage.get).toHaveBeenCalledWith({ key: 'dude' });
}); Not Working (Cap plugin object) import { Storage } from '@capacitor/storage';
...
it('can be spied upon', async () => {
spyOn(Storage, 'get').and.returnValue(Promise.resolve({ value: 'abides' }));
expect(await Storage.get({ key: 'dude' })).toEqual({ value: 'abides' });
expect(Storage.get).toHaveBeenCalledTimes(1);
expect(Storage.get).toHaveBeenCalledWith({ key: 'dude' });
}); |
Beta Was this translation helpful? Give feedback.
Replies: 4 comments 4 replies
-
I think the problem here is that So I simulated Jest's "Manual Mock" functionality to create POJOs for the tests. See this commit: https://github.com/kensodemann/test-cap-3/commit/b12dee0dc7f794e8ddf883f50c6c3b886071c243 This is pretty simple and straight forward, but would need to be documented if we end up running with this. Totally open to other suggestions as well. |
Beta Was this translation helpful? Give feedback.
-
@kensodemann Have you found a workaround for your issue? I have the same problem and nothing is working for me. I tried mocking the plugins as was suggested, but I still get ChunkLoadError(s). Thank you! |
Beta Was this translation helpful? Give feedback.
-
We now have a guide for this: https://capacitorjs.com/docs/guides/mocking-plugins |
Beta Was this translation helpful? Give feedback.
-
Here's an approach that works for me (at least with
|
Beta Was this translation helpful? Give feedback.
We now have a guide for this: https://capacitorjs.com/docs/guides/mocking-plugins