英文:
unexpected behaviors on classes when testing with jest
问题
我在我的项目上进行一些测试,遇到了一些奇怪的行为。
我的代码看起来像这样:
export class Variable {
  b;
  constructor() {
    this.b = 'B';
  }
  changeValue = () => {
    this.b = 'changed B';
  };
}
export class DerivedVariable {
  v;
  constructor(v: Variable[]) {
    this.v = v;
  }
}
export class Store {
  a;
  v;
  initialize = () => {
    this.a = new Variable();
  };
  get computedValue() {
    return [this.a];
  }
  get computedInstances() {
    return new DerivedVariable(this.computedValue);
  }
}
我的测试代码:
test('test', () => {
    const { a, computedValue, computedInstances, initialize } = new Store();
    initialize();
    expect(computedValue[0].b).toBe('B');
    computedValue[0].changeValue();
    expect(a.b).toBe('changed B');
    expect(computedInstances.v[0].b).toBe('changed B');
});
我想运行initialize函数会填充类变量,从而使测试通过。
然而,测试的结果却返回了类似于:
TypeError: Cannot read properties of undefined (reading 'b')
      24 |     initialize();
      25 |
    > 26 |     expect(computedValue[0].b).toBe('B');
Jest在创建类实例时是否具有异步行为呢?
提前感谢。
- 顺便说一下,当调用一个会改变类变量的函数后,我遇到了类似的问题,我认为这两个问题可能有关。
 
英文:
I'm working on some tests on my project, and have run in to some weird behaviors.
My code looks something like this:
export class Variable {
  b;
  constructor() {
    this.b = 'B';
  }
  changeValue = () => {
    this.b = 'changed B';
  };
}
export class DerivedVariable {
  v;
  constructor(v: Variable[]) {
    this.v = v;
  }
}
export class Store {
  a;
  v;
  initialize = () => {
    this.a = new Variable();
  };
  get computedValue() {
    return [this.a];
  }
  get computedInstances() {
    return new DerivedVariable(this.computedValue);
  }
}
and my test code:
test('test', () => {
    const { a, computedValue, computedInstances, initialize } = new Store();
    initialize();
    expect(computedValue[0].b).toBe('B');
    computedValue[0].changeValue();
    expect(a.b).toBe('changed B');
    expect(computedInstances.v[0].b).toBe('changed B');
  });
I figured running the initialize function would populate the class variable, which would allow the test to pass.
However, the results of the test returns something like:
 TypeError: Cannot read properties of undefined (reading 'b')
      24 |     initialize();
      25 |
    > 26 |     expect(computedValue[0].b).toBe('B');
Does jest have an asynchronous behavior when it comes to creating class instances?
Thanks in advance.
- On a side note, I've run into a similar issue when testing with class variables after calling a function that mutates it, I assume the two issues are related.
 
答案1
得分: 0
我很难相信我错过了如此明显的东西,
但我通过一些排除法和研究找出了问题所在。
我遇到了一个stackoverflow问题,它引导我朝着正确的方向前进。
显然,关于箭头函数、词法作用域等方面都没有问题,
我只是忘记了JavaScript中对象赋值的工作原理。
重新分配变量a将填充变量的内存地址到另一个值,
而测试代码中的解构a将指向“旧”的对象。
在代码中:
test('test', () => {
    const { a, computedValue, computedInstances, initialize } = new Store();
    // 变量a指向初始值,这将是undefined
    initialize(); 
    // 此时,a被分配了一个新创建的变量,这将使解构的"a"在这一点上过时
  });
英文:
wow, I can't believe I missed something so obvious,
but I was able to figure out what was wrong with some process of elimination and research.
I ran into a stackoverflow question which led me to the right direction.
Apparently there were no problems at all regarding arrow functions, lexical scopes and whatnot,
I had just forgotten about how object assignment in javascript works.
Reassigning the variable a would populate the variable with a memory address to another value,
and the destructured a in the test code would point to the "old" object
In code:
test('test', () => {
    const { a, computedValue, computedInstances, initialize } = new Store();
    // the variable a points to the initial value, which would be undefined
    initialize(); 
    // at this point, a is assigned a newly created Variable, which would make the destructured "a" obsolete at this point
  });
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论