Есть ли функция сопоставления равенства массивов, которая игнорирует позицию элемента в jest.js?

Я получаю, что .toEqual() проверяет равенство всех полей для простых объектов:

expect(
    {"key1":"pink  wool","key2":"diorite"}
).toEqual(
    {"key2":"diorite","key1":"pink wool"}
);

Так что это проходит.

Но то же самое не относится к массивам:

expect(["pink wool", "diorite"]).toEqual(["diorite", "pink wool"]);

Похоже, что в документах шутки нет функции сопоставления, которая делает это, то есть проверяет равенство двух массивов независимо от положения их элементов. Должен ли я тестировать каждый элемент в одном массиве против всех элементов в другом и наоборот? Или есть другой способ?


person Benjamin H Boruff    schedule 19.10.2016    source источник
comment
Все еще выпуск, может быть, мы сможем устроить пиар для Jest?   -  person hypeofpipe    schedule 30.11.2020


Ответы (9)


Нет встроенного метода для сравнения массивов без сравнения порядка, но вы можете просто отсортировать массивы, используя _ 1_ перед сравнением:

expect(["ping wool", "diorite"].sort()).toEqual(["diorite", "pink wool"].sort());

Вы можете проверить пример в этой скрипке.

person biphobe    schedule 21.10.2016
comment
это не сработает, если вы работаете с массивом объектов. Потому что объект будет преобразован в [Объект объекта] и не будет отсортирован. И ваше сравнение все равно может потерпеть неудачу. developer.mozilla.org/en-US/ docs / Web / JavaScript / Reference /. - person Avinav; 10.04.2019
comment
да, я имею в виду, что вы должны предоставить подходящий компаратор для функции сортировки в соответствии с типом данных. - person Avin Kavish; 10.02.2021

Собираем элементы в набор. Jest знает, как их сочетать.

expect(new Set(["pink wool", "diorite"])).toEqual(new Set(["diorite", "pink wool"]));
person 0xcaff    schedule 18.11.2018
comment
Это было введено в Jest 23.0.0, поэтому не будет работать с предыдущими версиями. - person jkondratowicz; 11.12.2018
comment
Это приведет к игнорированию повторяющихся значений, что, вероятно, не то, что вам нужно. ["a", "a", "b"] будет соответствовать ["a", "b"]. - person Jezzamon; 12.02.2019
comment
Не используйте это, поскольку повторяющиеся элементы не учитываются. Избегайте, прежде чем сломаете голову - person Jimmy Kane; 13.03.2020
comment
Я настоятельно рекомендую вам удалить этот ответ, поскольку он почти во всех отношениях уступает принятому. Единственный раз, когда я мог представить, что ваш ответ будет лучше, - это случай, когда у нас много дубликатов, и поэтому последующее сравнение может быть быстрее. Если это то, что вы хотите сказать, дайте пояснение. Если нет, ваш ответ вводит в заблуждение и может нанести большой ущерб приложению, поскольку он выглядит нормально и будет работать до тех пор, пока не перестанет работать, тогда ущерб может быть значительным. - person Xanlantos; 02.02.2021

Как уже упоминалось, expect.arrayContaining проверяет, содержит ли массив actual массив expected в качестве подмножества. Для проверки эквивалентности можно

  • либо утверждать, что длина обоих массивов одинакова (но это не приведет к появлению полезного сообщения об ошибке)
  • или утверждать обратное: что массив expected содержит массив actual:
// This is TypeScript, but remove the types and you get JavaScript
const expectArrayEquivalence = <T>(actual: T[], expected: T[]) => {
  expect(actual).toEqual(expect.arrayContaining(expected));
  expect(expected).toEqual(expect.arrayContaining(actual));
};

По-прежнему существует проблема, заключающаяся в том, что когда тест не проходит в первом утверждении, человек узнает только об элементах, отсутствующих в actual, и не о дополнительных элементах, которых нет в expected.

person nitzel    schedule 09.08.2019

это не дает точного ответа на вопрос, но все же может помочь людям, которые попадают сюда с помощью поиска Google:

если вас интересует только то, что подмножество массива содержит определенные элементы, используйте expect.arrayContaining() https://jestjs.io/docs/en/expect#expectarraycontainarray

e.g.,

expect(["ping wool", "diorite"])
  .toEqual(expect.arrayContaining(["diorite", "pink wool"]));
person Ulad Kasach    schedule 27.09.2018
comment
Это не приведет к ошибке, если у массивов есть дополнительные значения. Дело было в проверке равенства. - person Andreas Herd; 05.10.2018
comment
Вы всегда можете проверить длину массива, чтобы убедиться, что этот тест соответствует ожидаемому, а не подмножеству ожидаемого. - person Zakalwe; 10.07.2020

Если вы хотите сравнить два массива в JEST, используйте приведенную ниже модель.

Официальная ссылка: https://jestjs.io/docs/en/expect#expectarraycontainarray

const array1 = ['a', 'b', 'c'];
const array2 = ['a', 'b', 'c'];
const array3 = ['a', 'b'];


it("test two arrays, this will be true", () => { 
    expect(array1).toEqual(expect.arrayContaining(array2));
});

it("test two arrays, this will be false", () => { 
    expect(array3).toEqual(expect.arrayContaining(array1));
});
person Sergiu Mare    schedule 10.02.2021

Вы можете комбинировать использование наборов, как указано в этом ответе, с проверкой длины фактического результата и ожидания. Это проигнорирует положение элемента и одновременно защитит вас от дублирования элементов.

const materials = ['pink wool', 'diorite'];
const expectedMaterials = ['diorite', 'pink wool'];

expect(new Set(materials)).toEqual(new Set(expectedMaterials));
expect(materials.length).toBe(expectedMaterials.length);
person tymzap    schedule 04.05.2020

Если у вас нет массива объектов, вы можете просто использовать sort () функция для сортировки перед сравнением. (упоминается в принятом ответе):

expect(["ping wool", "diorite"].sort()).toEqual(["diorite", "pink wool"].sort());

Однако проблема возникает, если у вас есть массив объектов, и в этом случае функция sort не будет работать. В этом случае вам необходимо предоставить настраиваемую функцию сортировки. Пример:

const x = [
{key: 'forecast', visible: true},
{key: 'pForecast', visible: false},
{key: 'effForecast', visible: true},
{key: 'effRegForecast', visible: true}
]

// In my use case, i wanted to sort by key
const sortByKey = (a, b) => { 
  if(a.key < b.key) return -1; 
  else if(a.key > b.key) return 1; 
  else return 0; 
  }

x.sort(sortByKey)
console.log(x)

Надеюсь, это когда-нибудь поможет кому-нибудь.

person mukesh210    schedule 13.03.2020
comment
более компактный способ: const sortByKey = (a, b) = ›(a.key‹ b.key? -1: a.key ›b.key? 1: 0) - person Davide Rossetto; 13.05.2021

Работа еще продолжается, но это должно сработать, хотя сообщения об ошибках могут быть нечеткими:

expect.extend({
  arrayContainingExactly(receivedOriginal, expected) {
    const received = [...receivedOriginal];

    if (received.length !== expected.length) return {
      message: () => `Expected array of length ${expected.length} but got an array of length ${received.length}`,
      pass: false,
    };

    const pass = expected.every((expectedItem, index) => {
      const receivedIndex = findIndex(received, receivedItem => {
          if (expectedItem.asymmetricMatch) return expectedItem.asymmetricMatch(receivedItem);
          return isEqual(expectedItem, receivedItem);
      });
      if (receivedIndex === -1) return false;
      received.splice(receivedIndex, 1);
      return true;
    });

    return {
      message: () => 'Success',
      pass,
    }
  }
});

Затем используйте это так:

expect(['foo', 'bar']).arrayContainingExactly(['foo']) // This should fail

or

expect({foo: ['foo', 'bar']}).toEqual({
  foo: expect.arrayContainingExactly(['bar', 'foo'])
}) // This should pass

Мы перебираем каждое значение в цикле и удаляем его из полученного массива, чтобы мы могли воспользоваться преимуществом асимметричного сопоставления, предоставляемого Jest. Если бы мы просто хотели сделать прямую эквивалентность, это можно было бы упростить, просто сравнив 2 отсортированных массива.

Примечание. В этом решении используются findIndex и isEqual из lodash.

person gabeodess    schedule 17.02.2021

Другой способ - использовать настраиваемый сопоставитель .toIncludeSameMembers() из jest-community / jest-extended.

Пример из README

test('passes when arrays match in a different order', () => {
    expect([1, 2, 3]).toIncludeSameMembers([3, 1, 2]);
    expect([{ foo: 'bar' }, { baz: 'qux' }]).toIncludeSameMembers([{ baz: 'qux' }, { foo: 'bar' }]);
});

Возможно, нет смысла импортировать библиотеку только для одного сопоставителя, но у них есть много других полезных сопоставителей, которые я считаю полезными.

person Jay Wick    schedule 16.01.2020