如何在Angular 5服务的构造函数中进行间谍/模拟方法调用?

时间:2018-01-01 23:37:01

标签: angular unit-testing typescript jasmine angular5

我有一个服务,它在构造函数中进行2次方法调用:

  constructor(private http: HttpClient) {
    this.apiURL = environment.apiURL;
    this.method();
    this.method2().subscribe();
  }

我正在尝试在TestBed中测试此服务。但是,在TestBed.get(MyService)之前,我无法使用Jasmine的间谍进行间谍活动。

这是我的服务的TestBed配置:

  let myService: MyService;
  let backend: HttpTestingController;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [
        HttpClientModule,
        HttpClientTestingModule
      ],
      providers: [
        MyService
      ]
    }).compileComponents();

    myService = TestBed.get(MyService);
    backend = TestBed.get(HttpTestingController);

如何正确监视method()method2()并为其返回值。如果服务不是一个好的做法,那么将方法放在构造函数中吗?

method()method2()向服务器发送http调用,以“刷新”用户可能需要的数据,例如墙上的Posts。另一种方法是将Observable.timer设置为令牌的年龄,以便在满足令牌到期时自动注销应用程序。

1 个答案:

答案 0 :(得分:0)

如果methodmethod2是原型方法,它们可以在类原型上进行监视:

it('', () => {
  spyOn(MyService.prototype, 'method').and.callThrough();
  spyOn(MyService.prototype, 'method2').and.callThrough();
  const svc = TestBed.get(MyService);
  expect(svc['method']).toHaveBeenCalled();
  expect(svc['method2']).toHaveBeenCalled();
});

如果它们适合在构造函数中使用,它总是取决于方法。

如果方法返回订阅,则应将其保存为属性,因为稍后可能会取消订阅,例如在服务销毁时。

考虑到methodmethod2是异步的,这可能是反模式。如果它们触发了预期在服务实例化时完成的请求,则这将导致竞争条件,因为它们未完成,并且服务也不会公开promise或observable来跟踪请求的状态。正确的解决方案是不要在构造函数中调用它们,而是在适合异步提供程序初始化的某个地方调用它们,即APP_INITIALIZER或路由解析器。