Unit testing Angular 2 RC4:具有依赖项注入的单元测试组件—具有自己的

Unit testing Angular 2 RC4:具有依赖项注入的单元测试组件—具有自己的,unit-testing,typescript,dependency-injection,angular,jasmine,Unit Testing,Typescript,Dependency Injection,Angular,Jasmine,由于Angular团队不断升级/弃用Angular 2 RC版本中的内容,我遇到了这个问题 我有一个具有依赖注入(DI)的组件,它实际上是一个服务(在本例中是UserService)。这个用户服务当然有自己的一些DIs。在升级到Angular 2的最新RC4之后,我意识到我不能再创建类似的测试了 因此,由于文档中没有提到相关内容,所以我的代码(针对这个问题简化了) 我的组件: import { Component } from '@angular/core'; import { MdButton

由于Angular团队不断升级/弃用Angular 2 RC版本中的内容,我遇到了这个问题

我有一个具有依赖注入(DI)的组件,它实际上是一个服务(在本例中是UserService)。这个用户服务当然有自己的一些DIs。在升级到Angular 2的最新RC4之后,我意识到我不能再创建类似的测试了

因此,由于文档中没有提到相关内容,所以我的代码(针对这个问题简化了)

我的组件:

import { Component } from '@angular/core';
import { MdButton } from '@angular2-material/button';
import {
  MdIcon,
  MdIconRegistry
} from '@angular2-material/icon';
import { UserService } from '../../services/index';

@Component({
  moduleId: module.id,
  selector: 'logout-button',
  templateUrl: 'logout-button.component.html',
  styleUrls: ['logout-button.component.css'],
  providers: [MdIconRegistry, UserService],
  directives: [MdButton, MdIcon]
})
export class LogoutButtonComponent {

  constructor(public userService: UserService) {}

  /**
   * Call UserService and logout() method
   */
  logout() {
    this.userService.logout();
  }

}
import { Injectable } from '@angular/core';
import {
  Http,
  Headers
} from '@angular/http';
import {
  AuthHttp,
  JwtHelper
} from 'angular2-jwt';
import { Router } from '@angular/router';
import { UMS } from '../common/index';

@Injectable()
export class UserService {

  constructor(
    private router: Router,
    private authHttp: AuthHttp,
    private http: Http) {

      this.router = router;
      this.authHttp = authHttp;
      this.http = http;
    }

    /**
     * Logs out user
     */
    public logout() {
      this.authHttp.get(UMS.url + UMS.apis.logout)
      .subscribe(
        data => this.logoutSuccess(),
        err => this.logoutSuccess()
      );
    }

}
import { By }           from '@angular/platform-browser';
import { DebugElement } from '@angular/core';

import {
  beforeEach,
  beforeEachProviders,
  describe,
  expect,
  it,
  inject,
  fakeAsync,
  TestComponentBuilder
} from '@angular/core/testing';

import { AuthHttp } from 'angular2-jwt';
import { Router } from '@angular/router';
import { Http } from '@angular/http';
import { LogoutButtonComponent } from './logout-button.component';
import { UserService } from '../../services/index';

describe('Component: LogoutButtonComponent', () => {



  beforeEachProviders(() => [
    LogoutButtonComponent,
    UserService
  ]);

  it('should inject UserService', inject([LogoutButtonComponent],
    (component: LogoutButtonComponent) => {
      expect(component).toBeTruthy();
  }));

});
组件的DI、用户服务,如您所见,它有一些DI(路由器、AuthHttp和Http):

import { Component } from '@angular/core';
import { MdButton } from '@angular2-material/button';
import {
  MdIcon,
  MdIconRegistry
} from '@angular2-material/icon';
import { UserService } from '../../services/index';

@Component({
  moduleId: module.id,
  selector: 'logout-button',
  templateUrl: 'logout-button.component.html',
  styleUrls: ['logout-button.component.css'],
  providers: [MdIconRegistry, UserService],
  directives: [MdButton, MdIcon]
})
export class LogoutButtonComponent {

  constructor(public userService: UserService) {}

  /**
   * Call UserService and logout() method
   */
  logout() {
    this.userService.logout();
  }

}
import { Injectable } from '@angular/core';
import {
  Http,
  Headers
} from '@angular/http';
import {
  AuthHttp,
  JwtHelper
} from 'angular2-jwt';
import { Router } from '@angular/router';
import { UMS } from '../common/index';

@Injectable()
export class UserService {

  constructor(
    private router: Router,
    private authHttp: AuthHttp,
    private http: Http) {

      this.router = router;
      this.authHttp = authHttp;
      this.http = http;
    }

    /**
     * Logs out user
     */
    public logout() {
      this.authHttp.get(UMS.url + UMS.apis.logout)
      .subscribe(
        data => this.logoutSuccess(),
        err => this.logoutSuccess()
      );
    }

}
import { By }           from '@angular/platform-browser';
import { DebugElement } from '@angular/core';

import {
  beforeEach,
  beforeEachProviders,
  describe,
  expect,
  it,
  inject,
  fakeAsync,
  TestComponentBuilder
} from '@angular/core/testing';

import { AuthHttp } from 'angular2-jwt';
import { Router } from '@angular/router';
import { Http } from '@angular/http';
import { LogoutButtonComponent } from './logout-button.component';
import { UserService } from '../../services/index';

describe('Component: LogoutButtonComponent', () => {



  beforeEachProviders(() => [
    LogoutButtonComponent,
    UserService
  ]);

  it('should inject UserService', inject([LogoutButtonComponent],
    (component: LogoutButtonComponent) => {
      expect(component).toBeTruthy();
  }));

});
下面是组件的测试:

import { Component } from '@angular/core';
import { MdButton } from '@angular2-material/button';
import {
  MdIcon,
  MdIconRegistry
} from '@angular2-material/icon';
import { UserService } from '../../services/index';

@Component({
  moduleId: module.id,
  selector: 'logout-button',
  templateUrl: 'logout-button.component.html',
  styleUrls: ['logout-button.component.css'],
  providers: [MdIconRegistry, UserService],
  directives: [MdButton, MdIcon]
})
export class LogoutButtonComponent {

  constructor(public userService: UserService) {}

  /**
   * Call UserService and logout() method
   */
  logout() {
    this.userService.logout();
  }

}
import { Injectable } from '@angular/core';
import {
  Http,
  Headers
} from '@angular/http';
import {
  AuthHttp,
  JwtHelper
} from 'angular2-jwt';
import { Router } from '@angular/router';
import { UMS } from '../common/index';

@Injectable()
export class UserService {

  constructor(
    private router: Router,
    private authHttp: AuthHttp,
    private http: Http) {

      this.router = router;
      this.authHttp = authHttp;
      this.http = http;
    }

    /**
     * Logs out user
     */
    public logout() {
      this.authHttp.get(UMS.url + UMS.apis.logout)
      .subscribe(
        data => this.logoutSuccess(),
        err => this.logoutSuccess()
      );
    }

}
import { By }           from '@angular/platform-browser';
import { DebugElement } from '@angular/core';

import {
  beforeEach,
  beforeEachProviders,
  describe,
  expect,
  it,
  inject,
  fakeAsync,
  TestComponentBuilder
} from '@angular/core/testing';

import { AuthHttp } from 'angular2-jwt';
import { Router } from '@angular/router';
import { Http } from '@angular/http';
import { LogoutButtonComponent } from './logout-button.component';
import { UserService } from '../../services/index';

describe('Component: LogoutButtonComponent', () => {



  beforeEachProviders(() => [
    LogoutButtonComponent,
    UserService
  ]);

  it('should inject UserService', inject([LogoutButtonComponent],
    (component: LogoutButtonComponent) => {
      expect(component).toBeTruthy();
  }));

});
现在不要为这件事担心

如你所见,我;我在每个提供者之前的
上添加相关提供者

在这种情况下,我在运行测试时出错:

错误:路由器没有提供程序!(注销按钮组件->用户服务->路由器)

比如说,这是意料之中的

因此,为了避免出现这些错误,我还将服务的DIs添加到提供者中:

  beforeEachProviders(() => [
    LogoutButtonComponent,
    Router,
    AuthHttp,
    Http,
    UserService
  ]);
但现在我发现了这个错误:

错误:无法解析“路由器”的所有参数(?、?、?、?、?、?、?、?、?)。确保所有参数都用Inject修饰或具有有效的类型注释,并且“Router”用Injectable修饰

我真的想弄清楚发生了什么,所以我在这里找到了一些相关的答案,但都是过时的,涵盖了旧的
路由器弃用
angular2/路由器
,但两者都弃用,不涵盖此案例

我希望在这方面能得到一些帮助,也许还需要一些资源,因为我找不到与最新版本路由器相关的任何东西:
“@angular/Router”:“3.0.0-beta.2”
,以及
RC4

谢谢

更新

我设法绕过了上面的两个错误,现在我可以访问组件了。以下是描述代码:

describe('Component: LogoutButtonComponent', () => {

  let component: LogoutButtonComponent;
  let router: any = Router;
  let authHttp: any = AuthHttp;
  let http: any = Http;
  let service: any = new UserService(router, authHttp, http);

  beforeEachProviders(() => [
    LogoutButtonComponent
  ]);

  beforeEach(() => {
    component = new LogoutButtonComponent(service);
  });

  it('should inject UserService', () => {
    expect(component.userService).toBeTruthy();
  });

  it('should logout user', () => {
    localStorage.setItem('token', 'FOO');
    component.logout();
    expect(localStorage.getItem('token')).toBeUndefined();
  });

});
但是,似乎即使DI服务被注入并可访问,服务的DIs也不可访问。现在我得到了这个错误:

TypeError:this.authHttp.get不是函数


有什么想法吗?

看起来您遇到了依赖项循环问题,因为您的UserSerivce还需要注入AuthHttp、Http等。。。如果您需要测试您的组件,它确实会被干扰一次。 我的方法是创建一个mock UserSerivce并通过
UserService.logout()
方法返回预期的mock值,因为您不必知道UserService中到底发生了什么,只需要返回值:

let MockUserService = {
  logout() {
    // return some value you need 
  }
}
然后,在测试套件中:

import { provide } from '@angular/core'

beforeEachProviders(() => [
  provide(UserService, {useClass: MockUserService})
])

... detail test code here
我希望这对你有用。 这里有一个帖子对我很有帮助:
对于RC4,在测试中使用http需要一些变通方法。另请参见此问题(应在RC5中修复):

将此添加到我的unit-tests.html为我修复了它:

System.import('@angular/platform-browser/src/browser/browser_adapter').then(function(browser_adapter) {
    browser_adapter.BrowserDomAdapter.makeCurrent();
})

在从jasmine测试中获取使用http的服务时,我遇到了类似的问题。不幸的是,我还没有在最新的RC中找到关于这些类型测试的文档。您是否尝试过使用UserService和Router的模拟?tymspy抱歉,因为还有很多事情要做,还没有。但是谢谢,当我要尝试的时候,我会告诉你结果的。