我有一个与此类似的代码:
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
第
答案 0 :(得分:1)
这是因为this.a = a.slice()
只需要浅拷贝。但由于a
是嵌套数组,因此嵌套数组中的任何内容都将在this.a
和source
中可见。
你可以改变:
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]]);