I ended up ditching the default export:
// UniqueIdGenerator.js
export const uniqueIdGenerator = () => Math.random().toString(36).substring(2, 8);
And then I could use and spy it like this:
import * as UniqueIdGenerator from './UniqueIdGenerator';
// ...
const spy = jest.spyOn(UniqueIdGenerator, 'uniqueIdGenerator');
Some recommend wrapping them in a const object, and exporting that. I suppose you can also use a class for wrapping.
However, if you can't modify the class there's still a (not-so-nice) solution:
import * as UniqueIdGenerator from './UniqueIdGenerator';
// ...
const spy = jest.spyOn(UniqueIdGenerator, 'default');
Answer from thisismydesign on Stack OverflowI ended up ditching the default export:
// UniqueIdGenerator.js
export const uniqueIdGenerator = () => Math.random().toString(36).substring(2, 8);
And then I could use and spy it like this:
import * as UniqueIdGenerator from './UniqueIdGenerator';
// ...
const spy = jest.spyOn(UniqueIdGenerator, 'uniqueIdGenerator');
Some recommend wrapping them in a const object, and exporting that. I suppose you can also use a class for wrapping.
However, if you can't modify the class there's still a (not-so-nice) solution:
import * as UniqueIdGenerator from './UniqueIdGenerator';
// ...
const spy = jest.spyOn(UniqueIdGenerator, 'default');
Here is a way of doing it for a default export without modifying the import (or even needing an import in the test at all):
const actual = jest.requireActual("./UniqueIdGenerator");
const spy = jest.spyOn(actual, "default");
Cannot spy on individual functions that are individually exported
spy on pure functions exported as const
Spy on default exported function with Jest - javascript
Allow to spy on modules that export functions
Lately I've been writing pure functions more and more in my code, they convey meaning very well, are easy to write and test
Now that most of my logic is in pure function I tend to write them outside of components because they don't depend on the state of the component.
Example getUsername is pure and not used in the template and as such doesn't really need to be a method of the component.
@Component({selector: ..., templateUrl: ..., styleUrls: ...})
export class UserComponent implements OnInit {
@Input() user: User;
username: string
ngOnInit() {
this.username = getUsername(this.user);
}
}
export const getUsername = (user: User): string => `${user.firstname} ${user.lastname}`;When I have too many of these pure functions I sometimes move them to a helper file.
Everything works perfectly, except when I try to spy on them for unit testing. At this point jasmine refuses to spy on them (relevant github issue)
What do you guys think I should do ? Move my pure functions to method of components ? Change my helper files into services eventhough they don't use any state ?
I feel like I have to remove relevant information from my code (purity of the functions) for the sole reason of unit testing and I don't like it
Edit: spying on an exported function used to work but stopped working with Angular 9, cf this github issue