在Angular测试中更改组件变量会影响其他测试

时间:2019-01-18 13:00:13

标签: angular unit-testing jasmine

在测试中,我正在导入JSON文件以设置模拟值(通常将其作为@Input()传递到我的组件中)。

给我的印象是,如果使用beforeEach,则Angular测试会在每次测试运行之前重置组件变量。因此,在一个测试中更改组件变量的值不应影响同一测试床中的其他测试。

但是,我发现在测试中更改变量值时,beforeEach不会在下一次测试运行之前将其重置。

mock_board.json

{
   "board": {
     "type": "Archived"
   }  
}

component.spec.ts

import * as MockBoard from '../mock_board.json';
...

describe('MyComponent', () => {
  let component: MyComponent;
  let fixture: ComponentFixture(MyComponent);

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [
        ...
      ],
      declarations: [
        MyComponent
      ],
      providers: [
       ...
      ],
      schemas: [ NO_ERRORS_SCHEMA ]
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(MyComponent);
    component = fixture.componentInstance;
    component.board = MockBoard['board'];
    fixture.detectChanges();
  });

  it('should display title if board type is `Progress`', () => {
    component.board.type = 'Progress';

    ... // expectation here
  });

  it('should change the UI if board data changes', () => {
    console.log(component.board.type); // expected 'Archived' but returns 'Progress'
  });

  ...

如何确保每次运行测试之前始终将组件变量重置为原始变量?


编辑

我设法在StackBlitz here中复制了该错误。

在第二个测试中,以这种方式设置值:

component.board.type = 'Progress';

导致下一个测试失败,而像这样重写整个对象:

component.board = { id: 1, type: 'Progress' };

使下一个测试通过。

有什么想法吗?!

1 个答案:

答案 0 :(得分:1)

从您的StackBlitz(和许多日志语句!)看来,当您更改component.board中的值时,它也在更改data中的值。这是有道理的,因为beforeEach方法(component.board = data;)中的分配将只分配component.boarddata相同的指针。然后更改一个将更改另一个。

要克服这一点,您应该像某些注释中提到的那样,克隆data对象,而不是直接分配它。您可以使用JSON.parse(JSON.stringify(MockBoard['board']))(如 Jelle 所述),也可以使用类似Lodash的clone方法(对于更复杂的对象,则使用cloneDeep)。

Here is an updated StackBlitz,可用于与原始代码进行比较。