Я создаю приложение React Native с TypeScript и пишу свои модульные тесты с использованием Jest.
В настоящее время я пишу модульные тесты для экрана загрузки:
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.
Как вы можете видеть после монтирования компонента, я проверяю, есть ли токен.И в зависимости от токена я загружаю синхронизирую приложение с сервером (в getBootData
) и перехожу на соответствующий экран - либо Home
, либо обратно на Login
.
Вот тест, который янаписал для этого метода жизненного цикла:
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);
});
});
});
Моя цель состояла в том, чтобы шпионить за getToken()
методом, чтобы узнать, был ли он вызван.Но проблема в том, что это приводит к ошибке:
● 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)
КСТАТИ: Проверка на getBootData
также не пройдена.Я думал, что spyOn должен был оставить исходную реализацию функции без изменений?Apparently Но, видимо, он обменивается с неопределенным: (
Дополнительная информация
Вот так getToken
выглядит:
import { getGenericPassword } from "react-native-keychain";
export const getToken = (): Promise<boolean | string> =>
getGenericPassword().then(
creds => (typeof creds === "boolean" ? creds : creds.password)
);
У меня также естьпростой макет для React Native Keychain getGenericPassword
в папке __mocks__/
рядом с моими узлами-модулями, чтобы функция автоматически получала насмешку от Jest в других тестах, которым требуется эта функция:
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
Это может бытьчто эти две насмешки каким-то образом складываются и вызывают неопределенность? То, что говорит против этого, заключается в том, что у меня нет глобальной getBootData
насмешки, которая - как упоминалось выше - аналогично дает сбой.
Что происходит?Почему spyOn вызывает функцию undefined
?