Chai断言测试对象结构是否至少包含其他对象结构

Chai assertion testing whether object structure contains at least other object structure

我使用 Mocha 进行单元测试,使用 Chai 进行断言。

我想找到一个易于使用的解决方案来检查对象是否具有我的比较对象中定义的结构和属性。但我不需要对象完全相等。被测对象应该包含 至少 我的测试对象中的所有属性,但它也可能包含当时未被测试的其他属性。

所以,我想测试一个单元来检查它 returns 的对象是否至少有一个名为 'foo' 的 属性,它本身是一个至少包含属性 'bar' 值为 10。所以,我有这个预期的结果来测试:

var expected = {foo: {bar: 10}};

我调用我的单元并将我的测试对象放在一个变量中 sut:

var sut = MyUnit.myFunction();

所以对于各种 suts,我期望这些结果:

// Success. Exact match
{foo: {bar: 10}}

// Fail. Structure is ok, but property value is wrong.
{foo: {bar: 11}}

// Fail. property bar is missing.
{foo: {qux: 20}}

// Success. All properties match. Extra properties (baz) in sut are ignored:
{baz: 'a', foo: {bar: 10, baz: 20}}

然后我想以一种方便的方式进行比较。我可以单独测试所有属性或将其拆分为多个测试,但我希望我可以做类似

的事情
sut.should.deep.contain.all(expected);

然而,我得到了以下令人惊讶的结果,即使对象完全相同:

AssertionError: expected { foo: { bar: 10 } } to have a property 'foo' of { bar: 10 }, but got { bar: 10 }

当然,我试过了这个,还有一些其他的变体。最简单的相等性测试,如果对象包含额外的属性则不起作用。

sut.should.eql(expected);

AssertionError: expected { foo: { bar: 10, qux: 20 } } to deeply equal { foo: { bar: 10 } }

我测试了 havecontains 的其他组合以及 deepanyall,但 none 满意我的希望。

我发现重复的问题“Chai deep contains assertion on nested objects”,但唯一的(否决的)答案没有意义。它调用 deep.eql 是多余的,在上面它只是不起作用,因为它测试严格相等。

我知道我可以单独测试所有属性,但我希望有一种可读的单语句方式来测试一个对象是否 'a subset of' 另一个。

更新: 我最终使用了 Chai 的 Shallow Deep Equal 插件。

Chai 有几个插件可以解决这个问题。

柴子集

柴有这个subset plugin,应该可以做到这一点。

我在浏览器中使用 Mocha,虽然它应该与浏览器兼容,但我还没有让这个插件工作。

无论如何,这个库包含问题的通用答案,在包含它之后,下面的行应该可以工作:

sut.should.containSubset(expected);

柴浅深均等

chai-subset 似乎缺少在浏览器中 运行 它所需的版本,所以我继续寻找插件。我发现的另一个是 chai-shallow-deep-equal

这个插件在浏览器中也可以正常使用。在 downloading it from Git 后的几秒内启动并 运行ning 并使用插件页面上的描述,导致:

sut.should.shallowDeepEqual(expected);

它现在可以很好地忽略 sut 中的额外属性,但是当 expected 中的属性缺失或不同时,它也会给出很好的断言。您会收到这样的消息:

AssertionError: Expected to have "2" but got "20" at path "/foo/qux".

不过,它并未显示所有断言。如果对象中有两个错误,您只会得到一个(第一个)断言错误。对我来说,这不是真正的问题,但它可能会令人困惑,因为它可能看起来像是你所做的修复引入了一个新问题,而它已经存在。

柴模糊

我自己还没有尝试 chai-fuzzy, (GitHub),但它似乎也能解决同样的问题,而且它的存储库也包含插件的浏览器兼容版本。但是,它还需要另一个库 Underscore,就此目的而言,它似乎有点矫枉过正。它的语法如下所示:

sut.should.be.like(expected);

如果我理解有误,请纠正我,但以下内容适用于纯柴。

expect({foo: {bar: 10}}).to.have.deep.property('foo.bar', 10); // Success
expect({foo: {bar: 11}}).to.have.deep.property('foo.bar', 10); // Fail
expect({foo: {qux: 20}}).to.have.deep.property('foo.bar', 10); // Fail
expect({baz: 'a', foo: {bar: 10, baz: 20}}).to.have.deep.property('foo.bar', 10); // Success