首页 > 解决方案 > 单元测试用例:期望从构造函数中调用组件函数

问题描述

我有以下组件:

export class MyComponent {
   constructor() { this.getStorageData(); }
   getStorageData() {...}
}

我正在尝试测试以下情况:创建组件后,getStorageData应该调用该函数。这就是我尝试这样做的方式:

beforeEach(() => {
  fixture = TestBed.createComponent(MyComponent);
  component = fixture.componentInstance;
})

it('should create', async(()=> {
   var spy = spyOn(component, "getStorageData").and.callThrough();
   fixture.detectChanges();
   expect(component).toBeDefined();
   expect(component.getStorageData).toHaveBeenCalled();
}))

测试的最后一行总是未通过测试。我究竟做错了什么?

标签: angularjasmine

解决方案


之所以没有被调用,是因为该spyOn方法是在组件创建之后调用的,所以是在构造函数被调用之后。有几种方法可以解决这个问题:

  1. 将函数调用移动到ngOnInit钩子:
export class MyComponent {
  constructor() {}

  ngOnInit(): void {
    this.getStorageData();
  }

  getStorageData() {...}
}

而且您只需确保spyOn在第一个detectChanges(). 然后你可以像你一样离开测试


  1. 只需使用初始化组件new并将间谍添加到原型中:
it('should call getStorageData', function() {
  spyOn(MyComponent.prototype, 'getStorageData').and.callThrough();
  const component = new MyComponent();
  expect(MyComponent.prototype.getStorageData).toHaveBeenCalled();
});

您将自己提供任何可能的构造函数提供程序,因为依赖注入将不起作用


  1. 将间谍beforeEach放在原型上
beforeEach(() => {
  spyOn(MyComponent.prototype, 'getStorageData').and.callThrough();
  fixture = TestBed.createComponent(MyComponent);
  component = fixture.componentInstance;
})

it('should create', async(()=> {   
   fixture.detectChanges();
   expect(component).toBeDefined();
   expect(MyComponent.prototype.getStorageData).toHaveBeenCalled();
}))

您可能应该考虑隔离此测试,以确保它不会被本规范中的每个测试所监视。


推荐阅读