单元测试 – 角度2 RC4:具有依赖注入的单元测试组件具有自己的服务

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

我有一个具有依赖注入(DI)的组件,这实际上是一个服务(在这种情况下是UserService).这个UserService当然有一些自己的DI.在更新到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();
  }

}

组件的DI,UserService可以看到有一些DI(路由器,AuthHttp& Http):

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();
  }));

});

现在不要担心(它).

正如你所看到的,我将在前面的ProProvider中添加相关的提供者.

在这种情况下,当我运行测试时,我收到一个错误

Error: No provider for Router! (logoutButtonComponent -> UserService -> Router)

预计会说这个.

所以为了不让这些错误我也在服务提供商的DIs中添加

beforeEachProviders(() => [
    logoutButtonComponent,Router,AuthHttp,Http,UserService
  ]);

但现在我得到这个错误

Error: Cannot resolve all parameters for ‘Router'(?,?,?). Make sure that all the parameters are decorated with Inject or have valid type annotations and that ‘Router’ is decorated with Injectable.

我真的想弄清楚发生了什么,所以我在这里找到一些相关的答案,但是所有的都是过时的,涵盖了旧的路由器不推荐或angular2 / router,但都被弃用,并没有覆盖这种情况.

会喜欢这方面的一些帮助,也许有一些资源,因为我找不到与最新版本的路由器相关的任何内容:“@ angular / router”:“3.0.0-beta.2”和RC4.

谢谢

UPDATE!

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

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服务被注入和访问,服务的DI也不是这样.所以现在我得到这个错误

TypeError: this.authHttp.get is not a function

有任何想法吗?

看起来你正在遇到一个依赖循环问题,因为你的UserSerivce也需要注入AuthHttp,Http等…如果你需要测试你的组件,它真的会被打扰一次.
我的方式只是创建一个模拟UserSerivce并通过UserService.logout()方法返回预期的嘲笑值,因为你不必知道在UserService中发生了什么,只需要一个返回值:
let MockUserService = {
  logout() {
    // return some value you need 
  }
}

然后,在测试套件中:

import { provide } from '@angular/core'

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

... detail test code here

我希望这适合你.
这里有一个帮助我很多的帖子:
https://developers.livechatinc.com/blog/testing-angular-2-apps-dependency-injection-and-components/

相关文章

适配器模式将一个类的接口转换成客户期望的另一个接口,使得原本接口不兼容的类可以相互合作。
策略模式定义了一系列算法族,并封装在类中,它们之间可以互相替换,此模式让算法的变化独立于使用算法...
设计模式讲的是如何编写可扩展、可维护、可读的高质量代码,它是针对软件开发中经常遇到的一些设计问题...
模板方法模式在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中,使得子类可以在不改变算法结...
迭代器模式提供了一种方法,用于遍历集合对象中的元素,而又不暴露其内部的细节。
外观模式又叫门面模式,它提供了一个统一的(高层)接口,用来访问子系统中的一群接口,使得子系统更容...