使用模拟后端测试 HTTP
Testing HTTP with mockbackends
我正在为 Angular 中的服务构建测试。事实证明,构建模拟后端是一项真正的试验。我已经能够通过它成功地发出实际的 HTTP 请求来测试服务,但我想将这些与第三方分开。
我梳理了我能找到的两篇主要文章 (first, second as well as the angular docs。
当我向实际的第三方服务发出成功的 http 请求时,我必须使用 done();
来确保测试等待请求完成。看来这里也是一样的。如果我不使用它,即使 expect(1).toBe(2);
测试也会成功。当我使用它时,它会在等待调用完成时超时。错误:
Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
这是我的代码:
import {
it,
inject,
describe,
beforeEachProviders,
expect,
} from '@angular/core/testing';
import { BaseRequestOptions, Response, ResponseOptions, Http } from '@angular/http';
import { MockBackend, MockConnection } from '@angular/http/testing';
import { AccountService } from './../../source/scripts/services/account.service';
import { provide } from '@angular/core';
describe('AccountService', () => {
// let service;
beforeEachProviders(() => [
AccountService,
BaseRequestOptions,
MockBackend,
provide(Http, {
deps: [MockBackend, BaseRequestOptions],
useFactory: (backend: MockBackend, defaultOptions: BaseRequestOptions) => {
return new Http(backend, defaultOptions);
},
}),
]);
beforeEach(<any>inject([MockBackend], (backend: MockBackend) => {
const baseResponse = new Response(new ResponseOptions({ body: 'got response' }));
backend.connections.subscribe((c: MockConnection) => c.mockRespond(baseResponse));
}));
// We use 'done' for async callbacks (http calls)
it('should return mocked response', (done) => {
inject([AccountService], (testService: AccountService) => {
testService.getUsers().subscribe((res: Response) => {
expect(res.text()).toBe('got response');
expect(1).toBe(2);
done();
});
});
});
});
如何使用模拟后端正确测试 http 调用?我怀疑我上面引用的链接已经过时,或者他们没有确认测试实际上是在测试,而不是在没有 done();
.
异步的情况下给出误报
你们非常亲密。只有 async done
在这里不合适,因为 inject
必须替换这个匿名回调。所以这里是固定版本:
it('should return mocked response', inject([AccountService], (testService: AccountService) => {
testService.getUsers().subscribe((res: Response) => {
expect(res.text()).toBe('got response');
expect(1).toBe(2);
});
}));
另一个问题是缺少beforeEach
导入:
import {
it,
inject,
describe,
beforeEach, // <-- this one was missing
beforeEachProviders,
expect,
} from '@angular/core/testing';
所以有一个 Jasmine 的 beforeEach
实例不允许使用 inject
。
我正在为 Angular 中的服务构建测试。事实证明,构建模拟后端是一项真正的试验。我已经能够通过它成功地发出实际的 HTTP 请求来测试服务,但我想将这些与第三方分开。
我梳理了我能找到的两篇主要文章 (first, second as well as the angular docs。
当我向实际的第三方服务发出成功的 http 请求时,我必须使用 done();
来确保测试等待请求完成。看来这里也是一样的。如果我不使用它,即使 expect(1).toBe(2);
测试也会成功。当我使用它时,它会在等待调用完成时超时。错误:
Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
这是我的代码:
import {
it,
inject,
describe,
beforeEachProviders,
expect,
} from '@angular/core/testing';
import { BaseRequestOptions, Response, ResponseOptions, Http } from '@angular/http';
import { MockBackend, MockConnection } from '@angular/http/testing';
import { AccountService } from './../../source/scripts/services/account.service';
import { provide } from '@angular/core';
describe('AccountService', () => {
// let service;
beforeEachProviders(() => [
AccountService,
BaseRequestOptions,
MockBackend,
provide(Http, {
deps: [MockBackend, BaseRequestOptions],
useFactory: (backend: MockBackend, defaultOptions: BaseRequestOptions) => {
return new Http(backend, defaultOptions);
},
}),
]);
beforeEach(<any>inject([MockBackend], (backend: MockBackend) => {
const baseResponse = new Response(new ResponseOptions({ body: 'got response' }));
backend.connections.subscribe((c: MockConnection) => c.mockRespond(baseResponse));
}));
// We use 'done' for async callbacks (http calls)
it('should return mocked response', (done) => {
inject([AccountService], (testService: AccountService) => {
testService.getUsers().subscribe((res: Response) => {
expect(res.text()).toBe('got response');
expect(1).toBe(2);
done();
});
});
});
});
如何使用模拟后端正确测试 http 调用?我怀疑我上面引用的链接已经过时,或者他们没有确认测试实际上是在测试,而不是在没有 done();
.
你们非常亲密。只有 async done
在这里不合适,因为 inject
必须替换这个匿名回调。所以这里是固定版本:
it('should return mocked response', inject([AccountService], (testService: AccountService) => {
testService.getUsers().subscribe((res: Response) => {
expect(res.text()).toBe('got response');
expect(1).toBe(2);
});
}));
另一个问题是缺少beforeEach
导入:
import {
it,
inject,
describe,
beforeEach, // <-- this one was missing
beforeEachProviders,
expect,
} from '@angular/core/testing';
所以有一个 Jasmine 的 beforeEach
实例不允许使用 inject
。