http.post 在使用 karma+jasmine 测试 angular2 服务时不是函数错误

http.post is not a function error while testing angular2 service with karma+jasmine

我正在尝试使用模拟后端测试我的 angular2 服务,但我的 http.post 服务请求一直收到此错误。

这里是错误:enter image description here

我的服务代码是:

      @Injectable()
    export class AuthService {
      private _jwt: string;

      constructor(private router: Router, private http: Http, private locker: Locker,
                  private authHttp: AuthHttp, private jwtHelper: JwtHelper) {
        this._jwt = localStorage.getItem('id_token');
      }

      public signIn(user: any) {
        let body = JSON.stringify(user);
        let self = this;
        return this.http.post(loginPath, body, {
          headers: contentHeaders})
          .map( function (response) { //some code here}

    }


And my spec file is as follows:

import { TestBed, async, inject } from '@angular/core/testing';
import { AuthService } from './auth.service';
import { Router } from '@angular/router';
import {
  Http, BaseRequestOptions, ResponseOptions, Response, RequestMethod,
  HttpModule, XHRBackend
} from '@angular/http';
import { Locker } from 'angular2-locker';
import { AuthHttp, JwtHelper } from 'angular2-jwt';
import { MockBackend, MockConnection } from '@angular/http/testing';

class RouterStub {
  navigate() {

  }
}



describe('Auth Service Unit Tests', () => {
  let authService: AuthService = new AuthService(Router, Http, Locker, AuthHttp, JwtHelper );

  let mockbackend;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      providers: [
        MockBackend,
        BaseRequestOptions,

        {provide: Router, useClass: RouterStub},
        {provide: AuthService, userValue: authService},

        {
          provide: Http,
          useFactory: (backend: MockBackend, options: BaseRequestOptions) => {
            return new Http(backend, options);
          },
          deps: [MockBackend, BaseRequestOptions]
        }

      ],
      imports: [
        HttpModule
      ]
    });

    mockbackend = TestBed.get(MockBackend);

    /* const baseResponse = new Response(new ResponseOptions({body: 'response'}));
     mockbackend.connections.subscribe((c: MockConnection) => c.mockRespond(baseResponse));*/
  }));

    it('should respond when we subscribe to Sign in', async(() => {
      mockbackend.connections.subscribe((connection: MockConnection) =>{
        expect(connection.request.method).toBe(RequestMethod.Post);
        connection.mockRespond(new Response(new ResponseOptions({status: 201})));

      });

        let user = {email: 'test@sample.com', password: '12345'};
        authService.signIn(user).subscribe((res: Response) => {
          expect(res).toBeDefined();
          expect(res.status).toBe(200);
        });
    }));




  });

非常感谢任何帮助!提前致谢

快速更新(根据@Will 的建议):我对我的服务实例进行了更改,如图所示

{provide: AuthService, useClass: AuthService}

并在我的测试规范中使用它如下:

authService = TestBed.get(AuthService, null)

但我仍然得到如下错误:

Failed: authService.signIn is not a function
    TypeError: authService.signIn is not a function
        at src/base.spec.ts:57308:21

我希望像下面这样的东西能起作用。如果继续出现 TypeError: authService.signIn is not a function 之类的错误,您可能会检查 AuthService 是否正确导出和导入。要调试 authService 实例,您可以添加注释 console.log。在我编写的类似测试中,我发现不需要您拥有的 async() 包装器。

      @Injectable()
    export class AuthService {
      private _jwt: string;

      constructor(private router: Router, private http: Http, private locker: Locker,
                  private authHttp: AuthHttp, private jwtHelper: JwtHelper) {
        this._jwt = localStorage.getItem('id_token');
      }

      public signIn(user: any) {
        let body = JSON.stringify(user);
        let self = this;
        return this.http.post(loginPath, body, {
          headers: contentHeaders})
          .map( function (response) { //some code here}

    }


And my spec file is as follows:

import { TestBed, async, inject } from '@angular/core/testing';
import { AuthService } from './auth.service';
import { Router } from '@angular/router';
import {
  Http, BaseRequestOptions, ResponseOptions, Response, RequestMethod,
  HttpModule, XHRBackend
} from '@angular/http';
import { Locker } from 'angular2-locker';
import { AuthHttp, JwtHelper } from 'angular2-jwt';
import { MockBackend, MockConnection } from '@angular/http/testing';

class RouterStub {
  navigate() {

  }
}



describe('Auth Service Unit Tests', () => {
  let authService: AuthService;

  let mockbackend;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      providers: [
        MockBackend,
        BaseRequestOptions,

        {provide: Router, useClass: RouterStub},
        {provide: AuthService, useClass: AuthService},

        {
          provide: Http,
          useFactory: (backend: MockBackend, options: BaseRequestOptions) => {
            return new Http(backend, options);
          },
          deps: [MockBackend, BaseRequestOptions]
        }

      ],
      imports: [
        HttpModule
      ]
    });

    mockbackend = TestBed.get(MockBackend);
    authService = TestBed.get(AuthService, null);

    /* const baseResponse = new Response(new ResponseOptions({body: 'response'}));
     mockbackend.connections.subscribe((c: MockConnection) => c.mockRespond(baseResponse));*/
  }));

    it('should respond when we subscribe to Sign in', async(() => {
      // console.log(JSON.stringify(authService));
      mockbackend.connections.subscribe((connection: MockConnection) =>{
        expect(connection.request.method).toBe(RequestMethod.Post);
        connection.mockRespond(new Response(new ResponseOptions({status: 201})));

      });

        let user = {email: 'test@sample.com', password: '12345'};
        authService.signIn(user).subscribe((res: Response) => {
          expect(res).toBeDefined();
          expect(res.status).toBe(200);
        });
    }));




  });

如果这不起作用,我对这类问题的一般建议是,从 official Angular docs or a detailed blog like this 的示例测试开始,然后在本地为您 运行 获取它。然后慢慢更新测试,直到满足你的需求。