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

时间:2016-01-30 12:50:41

标签: javascript tdd bdd chai assertion

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

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

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

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

我调用我的单位并将我的测试主题放在变量sut中:

var sut = MyUnit.myFunction();

因此,对于各种各样的尝试,我期待这些结果:

// 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插件。

2 个答案:

答案 0 :(得分:9)

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

chai-subset

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

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

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

sut.should.containSubset(expected);

<强>柴浅深等于

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

答案 1 :(得分:1)

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

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