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

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

本文关键字:对象 结构 包含 其他 是否 断言 测试      更新时间:2023-09-26

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

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

因此,我想测试一个单元以检查它返回的对象是否至少具有一个名为"foo"的属性,该属性本身是一个至少包含值为 10 的属性"bar"的对象。因此,我有以下预期结果进行测试:

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

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

断言错误: 预期 { foo: { bar: 10 } } 具有 { bar: 10

} 的属性 'foo',但得到 { bar: 10 }

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

sut.should.eql(expected);
AssertionError: expected { foo: { bar: 10

, qux: 20 } } to deep equal { foo: { bar: 10 } }

我已经测试了havecontains以及deepanyall的其他组合,但没有一个满足我的愿望。

我发现了重复的问题"Chai deep 包含对嵌套对象的断言",但唯一(被否决(的答案没有意义。它调用deep.eql这是多余的,除此之外,它只是不起作用,因为它测试严格的平等性。

我知道我可以单独测试所有属性,但是如果有一个可读的单语句方法来测试一个对象是否是另一个对象的"子集",我会很好。

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

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

柴子集

Chai有一个子集插件,应该能够做到这一点。

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

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

sut.should.containSubset(expected);

柴浅深相等

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

这个插件也可以在浏览器中很好地使用。从 Git 下载并使用插件页面上的描述后,在几秒钟内启动并运行它,结果是:

sut.should.shallowDeepEqual(expected);

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

断言错误:预期有"2",但在路径"/foo/qux"处得到"20"。

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

柴模糊

我自己还没有尝试过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