是否有一个数组相等匹配函数忽略jest.js中的元素位置?

时间:2016-10-19 15:26:01

标签: jasmine jestjs

我得到.toEqual()检查普通对象的所有字段的相等性:

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

所以这就过去了。

但对于数组来说同样如此:

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

似乎没有匹配器函数在jest docs中执行此操作,即测试两个数组的相等性而不管其元素位置如何。我是否必须针对另一个阵列中的所有元素测试每个元素,反之亦然?或者还有另一种方式吗?

9 个答案:

答案 0 :(得分:23)

没有内置方法来比较数组而不比较顺序,但您可以在进行比较之前使用.sort()对数组进行排序:

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

您可以查看this fiddle中的示例。

答案 1 :(得分:10)

将元素放入集合中。笑话知道如何匹配这些。

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

答案 2 :(得分:4)

使用expect.arrayContaining() https://jestjs.io/docs/en/expect#expectarraycontainingarray

例如

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

答案 3 :(得分:2)

如上所述,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中没有的多余元素。

答案 4 :(得分:2)

如果您想在 JEST 中比较两个数组,请使用波纹管模型。

官方链接:https://jestjs.io/docs/en/expect#expectarraycontainingarray

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));
});

答案 5 :(得分:1)

如果没有对象数组,则可以简单地使用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)

希望有一天能对某人有所帮助。

答案 6 :(得分:0)

您可以结合使用this answer中所述的集合与检查实际结果和期望的长度。这将忽略元素位置,并同时保护您免受重复元素的侵害。

答案 7 :(得分:0)

仍在进行中,但这应该可以工作,尽管错误消息可能不清楚:

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

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

我们循环遍历每个值并将其从接收到的数组中删除,以便我们可以利用 Jest 提供的非对称匹配。如果我们只想做直接等价,这可以简化为只比较 2 个已排序的数组。

注意:此解决方案使用 findIndex 中的 isEquallodash

答案 8 :(得分:-2)

QUnit具有deepEqual功能 https://api.qunitjs.com/assert/deepEqual

或者你可以使用toBeTruthy匹配器和下划线

expect(isEqual(1,2)).toBeTruthy()

虽然你没有获得关于对象之间差异的任何细节