javascript - Jest spyOn face ca funcția să fie 'undefined'
Construiesc o aplicație React Native cu TypeScript și scriu testele mele unitare folosind Jest.
În prezent scriu testele unitare pentru ecranul de încărcare:
export class LoadingScreen extends Component<Props, object> {
componentDidMount = () => {
const { dispatch, navigation } = this.props;
getToken()
.then(key => {
if (typeof key === "string") {
getBootData(dispatch)
.then(() => navigation.navigate("HomeScreen"))
.catch(err => {
alert(err);
// TODO: Hide the splash screen, after componentDidMount finished.
navigation.navigate("LoginScreen");
});
} else {
// TODO: Hide the splash screen, after componentDidMount finished.
navigation.navigate("LoginScreen");
}
})
.catch(() => navigation.navigate("LoginScreen"));
};
// ... render() n' stuff.
Așa cum poți vedea, după ce componenta se montează, verific dacă există un token. Și în funcție de token, sincronizez aplicația cu serverul (în getBootData) și navighez către ecranul respectiv - fie Home, fie înapoi la Login.
Iată testul pe care l-am scris pentru această metodă a ciclului de viață:
describe("life cycle methods", () => {
describe("componentDidMount", () => {
const props = createTestProps({});
const wrapper = shallow<LoadingScreen>(<LoadingScreen {...props} />);
const getTokenSpy = jest.spyOn(secureStoreFunctions, "getToken");
const getBootDataSpy = jest.spyOn(bootDataFunctions, "getBootData");
beforeEach(() => {
jest.resetAllMocks();
getBootDataSpy.mockResolvedValueOnce(true);
wrapper.instance().componentDidMount();
});
it("should call getToken", () => {
expect(getTokenSpy).toHaveBeenCalledTimes(1);
});
it("should call getBootData", () => {
expect(getBootDataSpy).toBeCalledTimes(1);
});
});
});
Scopul meu era să spionez metoda getToken() pentru a vedea dacă a fost apelată. Dar problema este că acest lucru duce la eroarea:
● LoadingScreen › life cycle methods › componentDidMount › should call getToken
TypeError: Cannot read property 'then' of undefined
17 | componentDidMount = () => {
18 | const { dispatch, navigation } = this.props;
> 19 | getToken()
| ^
20 | .then(key => {
21 | if (typeof key === "string") {
22 | getBootData(dispatch)
at LoadingScreen.componentDidMount (app/screens/Loading/LoadingScreen.tsx:19:5)
at Object.beforeEach (app/screens/Loading/LoadingScreen.test.tsx:39:28)
BTW: Testul pentru getBootData eșuează și el. Credeam că spyOn ar trebui să păstreze implementarea originală a funcției intactă? 🤔 Dar aparent o înlocuiește cu undefined :(
Informații suplimentare
Așa arată getToken:
import { getGenericPassword } from "react-native-keychain";
export const getToken = (): Promise<boolean | string> =>
getGenericPassword().then(
creds => (typeof creds === "boolean" ? creds : creds.password)
);
De asemenea, am un mock simplu pentru getGenericPassword din React Native Keychain într-un folder __mocks__/ adiacent modulelor mele node, astfel încât funcția să fie mock-uită automat de Jest în alte teste care necesită această funcție:
const token = "abcdefghijklmnopqrstuvwxyz0123456789";
const credentials = {
username: "session",
password: token
};
export const setGenericPassword = jest.fn(
(username, password) => new Promise((resolve, reject) => resolve(true)) // eslint-disable-line no-unused-vars
);
export const getGenericPassword = jest.fn(
() => new Promise((resolve, reject) => resolve(credentials)) // eslint-disable-line no-unused-vars
);
export const resetGenericPassword = jest.fn(() => new Promise((resolve, reject) => resolve(true))); // eslint-disable-line no-unused-vars
S-ar putea ca aceste două simulări să se suprapună într-un fel și să cauzeze nedefinirea? Ceea ce vorbește împotriva acestui lucru este că nu am o simulare globală getBootData, care - după cum s-a menționat mai sus - eșuează în mod similar.
Ce se întâmplă? De ce face spyOn ca funcția să devină undefined?