【问题标题】:Angular2 - test that a injected private service method has been calledAngular2 - 测试注入的私有服务方法已被调用
【发布时间】:2016-09-21 18:00:43
【问题描述】:

首先,我知道我不应该测试私有方法,但是我觉得有时我应该测试是否基于某种逻辑调用了私有方法。

我正在围绕 Angular 2 http 服务构建一个包装服务,这样我就可以进行全局错误处理,而无需将代码写入每个 http 请求。

类的一个小样本是这样的:

export class ApiService {
  constructor(private http: Http, private error: Error, private apiConfig: ApiConfig) {}

  public get(url: string, options: RequestOptionsArgs={}): Observable<any> {
   return this.http.get(url, options).catch((error: any) => {
     this.error.dispatch(error);
     return error;
   });
  }
}

如果我想测试 get 方法并以错误响应模拟响应,以便触发 catch,我无法测试是否调用了 error.dispatch 方法,因为这是私有的。我不能窥探私有方法。

您可能会争辩说,我实际上只是在测试“catch”是否被触发,如果它显然会触发它内部的方法,但这只是测试 http 服务本身。如果'catch'被触发,我想确保error.dispatch已作为调用添加,如果由于某种原因它被另一个开发人员删除,则会失败。也许这是一种不好的测试方式?我愿意接受其他建议。

我可以像这样模拟私有类:

{ provide: Error, useClass: FakeError }

但是 ApiService 类的蓝图保持不变,现在的 FakeError 服务仍然是私有的。在 Java 中,您可以自己创建实例并将其注入,因为您拥有它,您可以访问它。我想我正在尝试在 jasmine/typescript/angular2 中找到一种方法来做到这一点??

【问题讨论】:

  • 可以监视私有方法。
  • @estus 这可能是真的,但我无法测试它,因为我使用的是打字稿,如果我尝试这样断言:expect(service.error.dispatch).to...然后 typescript linter 爆炸了,因为我无权访问 service.error 因为它是私有的

标签: angular jasmine angular2-testing


【解决方案1】:

这就是spies 可以提供帮助的地方。如果真正的Error 可以在没有 DI 的情况下实例化,你可以这样做

let error;
beforeEach(()=>{
   error = new Error();
   spyOn(error, 'dispatch');

  TestBed.configureTestingModule({
    providers: [
      { provide: Error, useValue: error }
    ]
  });
});

it('', ()=> {
  expect(error.dispatch).toHaveBeenCalled();
});

或者您可以忘记 Error 类并提供一个模拟。

class FakeError {
  dispatch = jasmine.createSpy('dispatch');
}

就像上面一样使用它。你不需要像上面那样打电话给spyOn。在这里,dispatch 已经是间谍了。

【讨论】:

  • 太棒了,非常感谢。一个问题,为什么我必须将间谍放在 beforeEach 而不是 it 块中。我试过了,它没有用,我很惊讶。有什么想法吗?
猜你喜欢
  • 1970-01-01
  • 2018-06-04
  • 2016-10-13
  • 2016-05-11
  • 1970-01-01
  • 2014-02-09
  • 1970-01-01
  • 2017-09-17
  • 1970-01-01
相关资源
最近更新 更多