首先:我知道Angular2处于alpha状态且频繁更改。
我正在使用Angular2。有一个带有 http 依赖关系的可注入服务,我想使用模拟后端进行测试。该应用程序启动时该服务正常运行,但我没有运气写测试并让模拟后端响应。有任何见解,在我错过的测试设置或实现中是否有明显的东西?
服务/ core.ts:
import { Injectable } from 'angular2/angular2';
import { Http } from 'angular2/http';
@Injectable()
export class CoreService {
constructor(public http:Http) {}
getStatus() {
return this.http.get('/api/status')
.toRx()
.map(res => res.json());
}
}
服务/ core_spec.ts:
import {
AsyncTestCompleter,
TestComponentBuilder,
By,
beforeEach,
ddescribe,
describe,
el,
expect,
iit,
inject,
it,
xit
} from 'angular2/test';
import { MockBackend, MockConnection, BaseRequestOptions, Http, Response } from 'angular2/http';
import { Injector, bind } from 'angular2/angular2';
import { ObservableWrapper } from 'angular2/src/core/facade/async'
import { CoreService } from 'public/services/core'
export function main() {
describe('public/services/core', () => {
let backend: MockBackend;
let response: Response;
let coreService: CoreService;
let injector: Injector;
afterEach(() => backend.verifyNoPendingRequests());
it('should get status', inject([AsyncTestCompleter], (async) => {
injector = Injector.resolveAndCreate([
BaseRequestOptions,
MockBackend,
bind(Http).toFactory((backend, options) => {
return new Http(backend, options)
}, [MockBackend, BaseRequestOptions]),
bind(CoreService).toFactory((http) => {
return new CoreService(http);
}, [Http])
]);
backend = injector.get(MockBackend);
coreService = injector.get(CoreService);
response = new Response('foo');
ObservableWrapper.subscribe<MockConnection>(backend.connections, c => {
expect(c.request.url).toBe('/api/status');
c.mockRespond(response);
});
// attempt #1: fails because res argument is undefined
coreService.getStatus().subscribe(res => {
expect(res).toBe('');
async.done();
});
// attempt #2: fails because emitter.observer is not a function
ObservableWrapper.subscribe(coreService.getStatus(), res => {
expect(res).toBe('');
async.done();
});
}));
});
}
相关: https://github.com/angular/angular/issues/3502 https://github.com/angular/angular/issues/3530
答案 0 :(得分:6)
我在寻找测试技巧的同时找到了这个主题,但我无法直接回答这个问题......
这个基于Angular RC.1
假设您的服务是:
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
@Injectable()
export class CoreService {
constructor(private http: Http) {}
getStatus() {
return this.http.get('/api/status');
}
}
对上述服务的测试将如下所示:
import {
beforeEach,
beforeEachProviders,
describe,
expect,
inject,
it,
} from '@angular/core/testing';
import { provide } from '@angular/core';
import { BaseRequestOptions, Response, ResponseOptions } from '@angular/http';
import { MockBackend, MockConnection } from '@angular/http/testing';
describe('Http', () => {
beforeEachProviders(() => [
CoreService,
BaseRequestOptions,
MockBackend,
provide(Http, {
useFactory: (backend: MockBackend, defaultOptions: BaseRequestOptions) => {
return new Http(backend, defaultOptions);
},
deps: [MockBackend, BaseRequestOptions]
})
]);
beforeEach(inject([MockBackend], (backend: MockBackend) => {
const baseResponse = new Response(new ResponseOptions({ body: 'status' }));
backend.connections.subscribe((c: MockConnection) => c.mockRespond(baseResponse));
}));
it('should return response when subscribed to getStatus',
inject([CoreService], (coreService: CoreService) => {
coreService.getStatus().subscribe((res: Response) => {
expect(res.text()).toBe('status');
});
})
);
})
你真正需要注意的是在beforeEachProviders
中进行适当的嘲弄。测试本身非常简单,最终订阅了服务方法。
注意:不要忘记先设置基本提供程序:
import { setBaseTestProviders } from '@angular/core/testing';
import {
TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS,
TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS,
} from '@angular/platform-browser-dynamic/testing';
setBaseTestProviders(TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS, TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS);
答案 1 :(得分:3)
自从提出这个问题以来,我们确实升级到Angular2 RC 1.我们的进口看起来像Wojciech Kwiatek(感谢您的回答!)但我们的测试策略略有不同。我们想要在请求和响应上断言。我们使用beforeEachProviders()
而不是beforeEach()
,我们创建了自己的注入器,并保存了对被测试服务和模拟后端的引用。这允许我们对请求进行断言并管理测试内部的响应,并允许我们在每次测试后使用verifyNoPendingRequests()
方法。
describe('core-service', () => {
let service: CoreService;
let backend: MockBackend;
beforeEach(() => {
injector = ReflectiveInjector.resolveAndCreate(<any> [
CoreService,
BaseRequestOptions,
MockBackend,
provide(Http, {
useFactory: (mockBackend, defaultOptions) => new Http(mockBackend, defaultOptions),
deps: [MockBackend, BaseRequestOptions]
})
]);
service = <CoreService> injector.get(CoreService);
backend = <MockBackend> injector.get(MockBackend);
});
afterEach(() => backend.verifyNoPendingRequests());
it('should get status', () => {
backend.connections.subscribe((c: MockConnection) => {
expect(c.request.url).toEqual('api/status');
c.mockRespond(new Response(new ResponseOptions({ body: 'all is well' })));
});
service.getStatus().subscribe((status) => {
expect(status).toEqual('all is well');
});
}));
});
编辑:Plunker更新为RC2。 https://plnkr.co/edit/nlvUZVhKEr8d2mz8KQah?p=preview