摩卡,数组和范围的数组

时间:2017-09-06 18:05:22

标签: javascript arrays mocha

我有一个与此类似的代码:

let Foo = class Foo {
    constructor(a) {
        this.a = a.slice();
    }

    bar() {
        this.set(0, 1, [1]);
        this.set(1, 1, [1]);
    }

    set(x, y, n) {
        this.a[x][y] = n;
    }

    get() {
        return this.a;
    }
};

module.exports = Foo;

所以属性whis是一个数组数组,一个修改它的set函数,一个使用set的函数和一个getter。

现在我用mocha编写单元测试:

const Foo = require('./../foo.js'),
    source = [[1, 2, 3], [4, 5, 6]],
    chai = require('chai'),
    expect = chai.expect;

describe('Foo', () => {
    describe('bar', () => {
        it('expect to modify the array', () => {
            let foo = new Foo(source);

            foo.bar();

            expect(foo.a).to.deep.equal([[1, [1], 3], [4, [1], 6]]);
        });
    });

    describe('get', () => {
        it('expect to return the array', () => {
            let foo = new Foo(source);
            expect(foo.get()).to.deep.equal([1, 2, 3]);
        });
    });
});

我在其中声明了source变量,并使用它来构建每个测试的新Foo

然而,结果是...... bar测试修改了foo测试中get的属性:

  Foo
    bar
      ✓ expect to modify the array
    get
      1) expect to return the array


  1 passing (19ms)
  1 failing

  1) Foo get expect to return the array:

      AssertionError: expected [ [ 1, [ 1 ], 3 ], [ 4, [ 1 ], 6 ] ] to deeply equal [ 1, 2, 3 ]
      + expected - actual

       [
      -  [
      -    1
      -    [
      -      1
      -    ]
      -    3
      -  ]
      -  [
      -    4
      -    [
      -      1
      -    ]
      -    6
      -  ]
      +  1
      +  2
      +  3
       ]

      at Proxy.assertEqual (node_modules/chai/lib/chai/core/assertions.js:1020:19)
      at Proxy.methodWrapper (node_modules/chai/lib/chai/utils/addMethod.js:57:25)
      at Context.it (test/foo.js:20:30)

在mocha测试中使用匿名函数而不是箭头函数不会改变任何内容,使用或不使用splice按值复制源。

我错过了什么吗?很明显,我以某种方式将同一个引用归因于foo两个属性同一个数组,但我无法弄清楚如何,更重要的是,如何确保我可以创建单独的foo

1 个答案:

答案 0 :(得分:1)

这是因为this.a = a.slice()只需要浅拷贝。但由于a是嵌套数组,因此嵌套数组中的任何内容都将在this.asource中可见。

你可以改变:

this.a = a.slice();

为:

this.a = (function deepSlice(a) {
    return Array.isArray(a) ? a.map(deepSlice) : a;
})(a);

请注意,您的第二次测试需要进行任何更改,因为您没有与source初始化的内容进行比较。所以改变:

expect(foo.get()).to.deep.equal([1, 2, 3]);

为:

expect(foo.get()).to.deep.equal([[1, 2, 3], [4, 5, 6]]);