用 Jest 测试 Sentry
Testing Sentry with Jest
我正在测试 React 的错误边界,并在 Codecov 中注意到我的 Sentry 函数的特定部分尚未经过测试。
我曾尝试使用 jest.mock("@sentry/browser") 和 mocking 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
的第一个参数,这是回调函数。
的补充。那里的解决方案需要手动调用回调(参见测试代码中的 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');
});
我正在测试 React 的错误边界,并在 Codecov 中注意到我的 Sentry 函数的特定部分尚未经过测试。
我曾尝试使用 jest.mock("@sentry/browser") 和 mocking 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
的第一个参数,这是回调函数。
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');
});