typescript - Jest/ Jasmine : Weird Execution Order Of beforeEach()

标签 typescript unit-testing testing jasmine jestjs

给定类:

export class Foo {
  private static _count = 0;
  id: number;
  constructor() {
    this.id = ++Foo._count; // starts with 1
  }
}

和测试套件:

describe('Foo Class', () => {
  describe('constructor', () => {
    const fooClassRef = Foo as any; // to pass typechecking
    beforeEach(() => {
      console.log(`start of beforeEach: ${fooClassRef._count}`);
      fooClassRef._count = 0;
      console.log(`end of beforeEach: ${fooClassRef._count}`);
    });
    describe('creating one Foo obj', () => {
      console.log(fooClassRef._count);
      const foo = new Foo();
      it('should have an id of 1', () => {
        expect(foo.id).toBe(1);
      });
    });
    describe('creating two Foo objs', () => {
      console.log(fooClassRef._count);
      const foo1 = new Foo();
      const foo2 = new Foo();
      it('should have ids of 1 and 2', () => {
        expect(foo1.id).toBe(1);
        expect(foo2.id).toBe(2);
      });
    });
  });
});

第二次测试失败:

expect(received).toBe(expected) // Object.is equality

    Expected: 1
    Received: 2

       |       const foo2 = new Foo();
       |       it('should have ids of 1 and 2', () => {
    >  |         expect(foo1.id).toBe(1);
       |                         ^
       |         expect(foo2.id).toBe(2);
       |       });
       |     });

生成的日志是:

0
1
start of beforeEach(): 3
end of beforeEach(): 0
start of beforeEach(): 0
end of beforeEach(): 0

似乎 beforeEach 代码直到所有测试都完成后才真正运行。

最佳答案

[这个答案与 Jest 和 Jasmine 都相关!]

上面示例中的错误是对嵌套 describeit 和设置/拆卸回调的工作方式的误解。

(注意开 Jest it只是test的别名)

想象一下,如果您在上面的每个 describe/it 调用之前添加一个 beforeEach,那么嵌套看起来像这样:

┬─ beforeEach 1
└┬ describe Foo Class
 ├─ beforeEach 2
 └┬ describe constructor
  ├── beforeEach 3
  ├─┬ describe creating one Foo obj
  │ ├─ * - originally constructed a Foo here (but not inside of a beforeEach)
  │ ├─ beforeEach 4A
  │ └─ it should have an id of 1
  └─┬ describe creating two Foo objs
    ├─ * - originally constructed 2 more Foo's here (but not inside of a beforeEach)
    ├─ beforeEach 4B
    └─ it should have ids of 1 and 2

describebeforeEachit 回调的运行顺序是:

  1. describe 回调中的代码最终首先运行。您可以认为 describe 代码的工作是注册 it/test 回调和 beforeEach 回调(以及beforeAll afterAllafterEach 回调!)。您的 describe 中真的不应该有任何代码(除了声明要引用的 var 之外)没有嵌套在 itbeforeEach 中 回调 - 这就是您的测试最初失败的最终原因。

  2. Jest 会将每个 it/test 回调注册为要运行的“测试”,并确保所有 beforeAllbeforeEachafterAllafterEach 回调会根据它们的嵌套适当运行。

在给定假设树(其中每一层都有一个 beforeEach)的情况下,按照这种方法,结果如下:

  1. 最初在这里构建了一个 Foo(但不在 beforeEach 内部)
  2. 最初在这里构造了另外 2 个 Foo(但不在 beforeEach 内部)
  3. 在每个 1 之前
  4. 在每个 2 之前
  5. 在每个 3 之前
  6. 在每个 4A 之前
  7. 它的 id 应该是 1
  8. 在每个 1 之前
  9. 在每个 2 之前
  10. 在每个 3 之前
  11. 在每个 4B 之前
  12. 它的 ID 应该是 1 和 2

这解释了日志的原始顺序。

为了更好地测试这一点,让我们使用以下测试代码:

beforeEach(() => {
  console.log(1);
  const fooClassRef = Foo as any;
  fooClassRef._count = 0;
});
describe('Foo Class', () => {
  beforeEach(() => console.log(2));
  describe('constructor', () => {
    beforeEach(() => console.log(3));
    describe('creating one Foo obj', () => {
      beforeEach(() => console.log('4A'));
      test('should have an id of 1', () => {
        console.log('A');
        const foo = new Foo();
        expect(foo.id).toBe(1);
      });
    });
    describe('creating two Foo objs', () => {
      let foo1;
      let foo2;
      beforeEach(() => {
        console.log('4B');
        foo1 = new Foo();
        foo2 = new Foo();
      });
      it('should have ids of 1 and 2', () => {
        console.log(`4B'`);
        expect(foo1.id).toBe(1);
        expect(foo2.id).toBe(2);
      });
      it('should originally start with ids of 1 and 2, but they could be changed', () => {
        console.log(`4B''`);
        expect(foo1.id).toBe(1);
        expect(foo2.id).toBe(2);
        foo2.id = 47;
        expect(foo1.id).toBe(1);
        expect(foo2.id).toBe(47);
      });
    });
  });
});

注意:

  • 我们将私有(private)静态属性的重置移动到测试套件顶层的 beforeEach - 因为如果 Foo 有,为您可以运行的每个 Foo 测试重置它可能是个好主意其他要测试的方法或逻辑。
  • 我们在“创建两个 Foo 对象”describe
  • 中添加了另一个测试
  • 我们添加了一个 beforeEach,我们在其中创建我们的 foo1foo2 到那个 describe 因为这是设置我们要为我们的两个“创建两个 Foo objs”测试做!

现在,我们所有的测试都通过了,这个测试套件的结果日志是:

1
2
3
4A
1
2
3
4B
4B'
1
2
3
4B
4B''

引用

关于typescript - Jest/ Jasmine : Weird Execution Order Of beforeEach(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54166833/

相关文章:

node.js - 通过将 useNewUrlParser 设置为 true 来避免 "current URL string parser is deprecated"警告

c# - 在测试初始化​​方法中模拟 HttpContext.Current

安卓 Espresso 。 perform(click()) 等待通过单击按钮启动的任务完成

ruby-on-rails - 如何在 Rails 中测试任意路由?

javascript - AngularJS Jasmine spyOn : number is not a function

java - 玩!框架 2.2.0 : impossible to debug in Eclipse

typescript - 是否可以扩展可能为 Null 的类型?

reactjs - 如何使用 react-native-testing-library getByRole

javascript - 如何让 Visual Studio Intellisense 显示 javascript 回调中的属性?

unit-testing - 在进行 TDD 时,您如何保持纪律?