Нечеткие проверки с плавающей запятой против фиктивных аргументов вызова в Шутку

#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.