#javascript #typescript #jestjs
Вопрос:
Дана функция с сигнатурой
interface Position {
x: number, y: number
}
function f(position: Position): void { … }
Я хочу издеваться над этим в тесте
// given
const f = jest.fn()
// when
// exercise SUT
// then
expect(f).toHaveBeenCalledWith<Position>({x: 1.0, y: 1.0});
Но, к сожалению, я имею дело с плавающими точками, поэтому мне нужна проверка, чтобы обеспечить некоторую свободу действий. Теперь я мог бы сделать
expect(f.mock.calls[0][0].x).toBeCloseTo(1, 1);
expect(f.mock.calls[0][0].y).toBeCloseTo(1, 1);
Но это очень быстро устаревает. Есть запрос, который, по мнению разработчиков Jest, не требует включения в Jest, и соответствующий expect
пакет, но он не делает того, что я хотел бы сделать! Что-то вроде:
expect(f).toHaveBeenCalledWith(
expect.objectContaining({
x: expect.numberCloseTo(1),
y: expect.numberCloseTo(1)
});
Есть ли что-то подобное или мне нужно сделать свой собственный?
Комментарии:
1. Нет, встроенного нет, но вы можете добавить свой собственный с помощью
expect.extend
Ответ №1:
Как уже намекал Алексей, мне нужно было написать свой собственный сопоставитель. Итак, вот оно:
declare global {
namespace jest {
interface Expect {
numberCloseTo(expected: number, precision?: number): any;
}
}
}
expect.extend({
numberCloseTo(actual: number, expected: number, precision: number = 2) {
expect(actual).toBeCloseTo(expected, precision);
return { message: () => "This shouldn't happen.", pass: true };
},
});
И вот как я это использую:
expect(f).toHaveBeenCalledWith(
expect.objectContaining<Position>({
x: expect.numberCloseTo(1, 1),
y: expect.numberCloseTo(1, 1),
})
);
Расширение уже существующих сопоставителей в шутку очень неудобно, и я предполагаю, что это сделано специально. Итак, нам нужно включить фиктивное сообщение.
Только TS declare global
и т. Д. Могут быть удалены, если вы используете Flow или обычный JS.