我正在尝试在测试我的Angular应用时模拟一些http请求。我通过使用Angular的MockBackEnd和MockConnection在互联网上关注使用fakeBackendProvider的流行示例。虽然我很了解代码,但我想更详细地了解这些提供商的内部工作。
他们如何拦截http请求?例如,当我的代码调用http.get()时,他们会联系到什么,谁替换了什么,以及如何?
任何参考资料都非常有用。
答案 0 :(得分:2)
尝试使用角度为4.3.X的新增的HttpClient。它提供了实现HttpInterceptor的简便方法。 拦截,
使用具有Intercept方法的HttpInterceptor接口,您必须在类中覆盖它。 下面给出的示例代码,
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpResponse, HttpErrorResponse } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/Observable/throw';
import 'rxjs/add/operator/catch';
import 'rxjs/add/Observable/of';
import 'rxjs/add/operator/do';
export class YourInterceptor implements HttpInterceptor{
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>>{
// Your interceptor code comes here.
// you wish to change the request, change here.
request = request.clone({
setHeaders: {
Authorization: `Bearer ${this.auth.getToken()}`
}
});
return next.handle(request);
}
}
我认为你也在努力编写单元测试,为了做到这一点
Angular 4提供了两个很棒的类来使用HttpTestingController,HttpClientTestingModule。在使用之前,请确保在module.ts文件中提供HttpClientModule。
import { TestBed, inject, getTestBed } from '@angular/core/testing';
import { HttpClient, HttpClientModule } from '@angular/common/http';
import { HttpTestingController, HttpClientTestingModule } from '@angular/common/http/testing';
import { YourService } from './get-name-service.service';
describe('YourService', () => {
let injector: TestBed;
let httpMock: HttpTestingController;
let yourService: YourService;
beforeEach(() => {
TestBed.configureTestingModule({
imports:[HttpClientTestingModule],
providers: [YourService]
});
injector = getTestBed();
httpMock = injector.get(HttpTestingController);
yourService = TestBed.get(YourService);
});
describe('#getUsers', () => {
it('should return an Observable<User[]>', () => {
const dummyUsers = [
{ login: 'John' },
{ login: 'Doe' }
];
yourService.getNames().subscribe(users => {
console.log('I am here in yourService method');
expect(users.length).toBe(2);
expect(users).toEqual(dummyUsers);
});
const req = httpMock.expectOne('http://localhost:8080/dev/getNames');
expect(req.request.method).toBe("GET");
req.flush(dummyUsers);
});
});
});
答案 1 :(得分:1)
对于mockbackend,你可以做这样的事情,
在您的应用程序中包含正确的提供程序,如下所示,在您的情况下,它将是Http。 ......提供者:[Http,...]
如果您注意到我们使用了ReflectiveInjector类和方法resolveAndCreate,那么您的测试文件将包含以下代码或配置。此方法将帮助您创建具有所有依赖项的必需类的对象。 ex this.yourService = this.injector.get(YourService);
以下两行将帮助您的测试代码与虚假后端连接
{provide: ConnectionBackend, useClass: MockBackend},
{provide: RequestOptions, useClass: BaseRequestOptions},
提供和useClass,现在无论何时创建ConnectionBackend类对象,它都将与MockBackend类对象一起映射,
现在每个示例的测试用例(&#39; getNames()都应返回一些名称&#39;,可以使用this.lastConnection将用于连接你的mockedbackend,你必须创建一个使用下面的代码片段中的Response和ResponseOptions类进行响应。
describe('MockBackend NameService Example', () => {
beforeEach(() => {
this.injector = ReflectiveInjector.resolveAndCreate([
{provide: ConnectionBackend, useClass: MockBackend},
{provide: RequestOptions, useClass: BaseRequestOptions},
Http,
YourService,
]);
this.yourService = this.injector.get(YourService);
this.backend = this.injector.get(ConnectionBackend) as MockBackend;
this.backend.connections.subscribe((connection: any) => this.lastConnection = connection);
});
it('getNames() should return some names', fakeAsync(() => {
let result: String[];
this.yourService.getNames().then((names: String[]) => result = names);
this.lastConnection.mockRespond(new Response(new ResponseOptions({
body: JSON.stringify({data: ["Deepak Test1", "Deepak Test2"]}),
})));
tick();
expect(result.length).toEqual(2, 'should contain given amount of Names');
expect(result[0]).toEqual("Deepak Test1", ' NAME_ONE should be the first Name');
expect(result[1]).toEqual("Deepak Test2", ' NAME_TWO should be the second Name');
}));
});