【发布时间】:2017-07-04 18:54:53
【问题描述】:
虽然我知道测试代码的理想方式是像在生产中一样使用它,因此不直接处理私有属性和方法 TypeScript 让我有点困惑。
我有一个用户服务。
// user.service.ts
import {Injectable} from '@angular/core';
import {AppHttpService} from '../app-http/app-http.service'
@Injectable()
export class UserService {
constructor(private appHttp: AppHttpService) {
}
}
如图所示,它依赖于具有私有属性和方法的 appHttp 服务,假设看起来像这样:
// app-http.service.ts
@Injectable()
export class AppHttpService {
private apiUrl = 'my domain';
constructor(private http: Http, private authHttp: AuthHttp) {
}
post(body): Observable<any> {
return this.http.post(this.apiUrl, body)
.map((res)=>res)
.catch((err)=>null);
}
}
为了在我的用户服务上运行一个独立的测试,我想给它一个我的 appHttp 服务的简单模拟。不幸的是,如果我只是模拟 appHttp 的公共方法、属性并将其提供给我的构造函数,如下所示:
// user.service.spec.ts
describe('', () => {
let appHttpMock = {
post: jasmine.createSpy('post')
};
let service = new UserService(appHttpMock);
beforeEach(() => {
})
it('', () => {
})
})
我收到一条错误消息:
Error:(11, 33) TS2345:Argument of type '{ post: Spy; }' is not assignable to parameter of type 'AppHttpService'. Property 'apiUrl' is missing in type '{ post: Spy; }'.
如果我将我的模拟更改为简单地添加属性,我会收到另一个错误,抱怨它不是私有的。如果我创建一个真正的模拟类,例如:
// app-http.mock.ts
export class AppHttpMockService {
private apiUrl = 'my domain';
constructor() {
}
post() {
}
}
我仍然会收到另一个 TypeScript 错误:
Error:(8, 33) TS2345:Argument of type 'AppHttpMockService' is not assignable to parameter of type 'AppHttpService'. Types have separate declarations of a private property 'apiUrl'.
在没有 TypeScript 对 mock 的私有属性和方法大惊小怪的情况下,什么是运行独立测试(即不需要耗时创建测试平台的测试)的干净方法?
【问题讨论】:
-
我建议您查看官方 Angular 2 测试指南,因为您不是在测试“角度方式”。使用
Testbed和configureTestingModule解决了这个问题。 angular.io/docs/ts/latest/guide/testing.html#!#testbed -
使用提供者在实例化时注入你的模拟。这就是依赖注入的目的。他们是 angular.io 关于如何做到这一点的好文档。
-
你可以将
appHttpMock的类型指定为any,强制TypeScript放松类型检查。 AFAIK,您还可以使用 jasmine.createSpyObj() 创建整个模拟对象,并假装结果是 AppHttpMockService:let appHttpMock = jasmine.createSpyObj(...) as AppHttpService;。 -
而且似乎在 jasmine d.ts 文件中声明了一个通用方法来做到这一点:
jasmine.createSpyObj<AppHttpService>(...) -
@Adam 谢谢,我实际上是使用带有测试台的“角度方式”编写我的集成测试(要清楚,我的意思是根据 Angular 进行集成,我在这些测试中也使用模拟作为依赖项) .不幸的是,即使使用模拟,这些测试也可能需要 500-1000 毫秒才能运行,并且如果您使用的是 TDD、BDD,则无法很好地扩展。我认为这是一种更快的不涉及 Angular 的逻辑测试方法。
标签: angular typescript