Я тестирую свои границы ошибок для React и заметил в Codecov, что есть определенная часть моей функции Sentry, которая не была протестирована.
Я пытался использовать jest.mock("@sentry/browser") и издеваться над Sentry, однако, похоже, не удалось проверить строки. Импорт Sentry издевается правильно, но не scope.
Вот пример моей попытки издеваться.
import * as Sentry from "@sentry/browser"
const mock_scope = jest.fn(() => {
return { setExtras: null }
})
Sentry.withScope = jest.fn().mockImplementation(mock_scope)





Непроверенные строки — это функция обратного вызова, которая передается Sentry.withScope:
scope => {
scope.setExtras(errorInfo);
Sentry.captureException(error);
}
Поскольку Sentry.withScope был смоделирован, вы можете использовать mockFn.mock.calls для получения переданной ему функции обратного вызова.
Как только вы получили функцию обратного вызова, вы можете вызвать ее напрямую, чтобы протестировать.
Вот немного упрощенный рабочий пример:
import * as Sentry from '@sentry/browser';
jest.mock('@sentry/browser'); // <= auto-mock @sentry/browser
const componentDidCatch = (error, errorInfo) => {
Sentry.withScope(scope => {
scope.setExtras(errorInfo);
Sentry.captureException(error);
});
};
test('componentDidCatch', () => {
componentDidCatch('the error', 'the error info');
const callback = Sentry.withScope.mock.calls[0][0]; // <= get the callback passed to Sentry.withScope
const scope = { setExtras: jest.fn() };
callback(scope); // <= call the callback
expect(scope.setExtras).toHaveBeenCalledWith('the error info'); // Success!
expect(Sentry.captureException).toHaveBeenCalledWith('the error'); // Success!
});
Обратите внимание, что эта строка:
const callback = Sentry.withScope.mock.calls[0][0];
... получает первый аргумент первого вызова Sentry.withScope, который является функцией обратного вызова.
Идеально - это сработало как шарм. Раньше я не использовал mock.call, это была недостающая часть моих знаний, чтобы заставить это работать.
Вы спасли меня этим ответом. Я провел немало времени, ломая голову, задаваясь вопросом, как проверить именно эту ситуацию. Спасибо за ответ!
Это было очень полезно и для меня!
Дополнение к принятый ответ. Решение требует ручного вызова обратного вызова (см. строку callback(scope); // <= call the callback в тестовом коде).
Вот как заставить его работать автоматически:
import * as Sentry from '@sentry/browser'
jest.mock('@sentry/browser')
// Update the default mock implementation for `withScope` to invoke the callback
const SentryMockScope = { setExtras: jest.fn() }
Sentry.withScope.mockImplementation((callback) => {
callback(SentryMockScope)
})
И тогда тестовый код становится таким:
test('componentDidCatch', () => {
componentDidCatch('the error', 'the error info');
expect(SentryMockScope.setExtras).toHaveBeenCalledWith('the error info');
expect(Sentry.captureException).toHaveBeenCalledWith('the error');
});
Поскольку это сторонняя функция, я бы предложил использовать spyOn для объекта
Sentryи методwithScope