使用模拟后端测试 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