【问题标题】:Chai assertion testing whether object structure contains at least other object structureChai 断言测试对象结构是否至少包含其他对象结构
【发布时间】:2016-01-30 12:50:40
【问题描述】:

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

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

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

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

我打电话给我的单位并将我的测试对象放在一个变量sut

var sut = MyUnit.myFunction();

因此,对于各种 sut,我期望这些结果:

// 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: 预期 { foo: { bar: 10 } } 的属性 'foo' 为 { bar: 10 },但得到了 { bar: 10 }

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

sut.should.eql(expected);

AssertionError: 预期 { foo: { bar: 10, qux: 20 } } 深度等于 { foo: { bar: 10 } }

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

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

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

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

【问题讨论】:

标签: javascript tdd bdd chai assertion


【解决方案1】:

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

柴子集

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

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

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

sut.should.containSubset(expected);

chai-shallow-deep-equal

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

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

sut.should.shallowDeepEqual(expected);

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

AssertionError:预期有“2”,但在路径“/foo/qux”处得到“20”。

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

柴模糊

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

sut.should.be.like(expected);

【讨论】:

    【解决方案2】:

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

    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
    

    【讨论】:

    • 感谢您与我一起思考。您的代码一次测试一个属性。我认识到这会很好,但我希望有一种更简单的方法来检查更复杂的选项。 Foo 和 bar 当然是一个例子,我的实际对象要复杂一些,我必须测试(仅在本例中)多个级别的十几个属性。
    • 那我的回答确实不正确。我也不知道 chai-subset,我只是从你的答案中查到了。很高兴知道。我通常采取愚蠢的方式逐个属性地检查事物,但我也喜欢我的测试简单而愚蠢:)
    • @x_maras - 第一个和最后一个示例在 chai 4.1.2 中不起作用。没有费心去测试其他人。
    • @Roobie 这个答案来自近 2 年前(2016 年 1 月),正如您所见,当时运行代码没有问题。去年我没有使用 chai,但我只是注意到 chai 的第 4 版于 2017 年 5 月发布。在他们的发行说明中,他们指定他们将此功能更改为严格。检查发行说明的第三个项目符号。他们用嵌套替换了这个。 github.com/chaijs/chai/releases/tag/4.0.0
    猜你喜欢
    • 2023-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-09
    • 1970-01-01
    • 2011-08-02
    相关资源
    最近更新 更多