12

由於Angular團隊不斷升級/棄用Angular 2 RC版本中的內容,所以遇到此問題。Angular 2 RC4:具有依賴注入服務的單元測試組件具有自己的服務

我有一個組件具有依賴注入(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 whic你可以看到有一些的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(); 
    })); 

}); 

現在不要擔心它(它)。

正如你所看到的,我在beforeEachProviders上添加相關的提供者。

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

其中,預計讓我們說:

在這種情況下,當我進行的測試,我發現了一個錯誤。

所以爲了不要讓那些我加入該服務的的DI在供應商還錯誤:

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.

我真的想弄清楚發生了什麼,所以我在這裏找到了一些相關的答案,但是所有都過時了,涵蓋舊的router-deprecatedangular2/router,但兩者都被棄用,並且不涵蓋這種情況。

會喜歡這個的一些幫助,也許一些資源,因爲我找不到有關最新版本的路由器的任何東西:"@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服務注入和訪問該服務的DI是不是。所以現在我得到這個錯誤:

TypeError: this.authHttp.get is not a function

任何想法?

+0

我有得到一個服務類似的問題在茉莉花測試中使用http。不幸的是,我還沒有發現很多關於最新RC的這些類型測試的文檔。 – jsight

+0

您是否嘗試使用UserService和Router的模擬器? – tymspy

+0

@tymspy對不起,因爲有很多事情要做,還沒有。但是,謝謝,當我要嘗試它時,我會通知你有關結果。 –

回答

3

它看起來像你遇到了依賴性循環問題,因爲你的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/

0

隨着RC4,在測試中使用http需要一些解決方法。也看到這個問題(應固定在RC5):

https://github.com/angular/angular/issues/9294

添加該到我的單位tests.html固定對我來說:

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