2016-12-29 25 views
0

我正在嘗試爲Angular 2服務設置Karma Jasmine Unit測試。該服務被稱爲CreditService。該服務有一個可觀察的屬性_credit $並實現ng2-redux選擇器@select(s => s.credit)從Redux商店獲得信用對象。Angular 2 Unit測試使用Observable和Redux Rxjs選擇器的服務

import {Injectable, Inject} from '@angular/core'; 
import {ICreditData, ICreditSubmissionData, ContractType, ICredit} from '../../store/type-store/credit.types'; 
import 'rxjs/add/operator/map'; 
import {AppStateService} from '../app-state-service/app-state-service'; 
import {select} from 'ng2-redux'; 
import {Observable} from 'rxjs'; 
import {PromiseService} from '../promise/promise-service'; 


export interface ICreditResponse { 
    errors?: string[]; 
    token?: string; 
    response?: ICreditData; 
    submission?: ICreditSubmissionData; 
} 

export interface ICreditLead { 
    address: string; 
    aptSuite: string; 
    city: string; 
    state: string; 
    zipCode: number; 
    email: string; 
    monthlyIncome: number; 
    birthDate: string; 
    socialSec: number; 
    contactPolicy: boolean; 
} 

@Injectable() 
export class CreditService { 

    @select(s => s.credit) 
    private _credit$: Observable<ICredit>; 
    public isPostGA2: boolean = false; 

    constructor(@Inject(AppStateService) private _appStateService: AppStateService, 
       @Inject(PromiseService) private _promiseService: PromiseService) { 
    this.setupSubscriptionForPostGA2(); 
    } 
    /** 
    * Method will setup subscription to determine of credit has been 
    * pulled or credit has already been pulled and exists in the Redux store. 
    */ 
    public setupSubscriptionForPostGA2(): void { 
    // subscribe to the store check for isPostGA2 
    this._credit$.subscribe(
     credit => { 
     let creditDataExists = (credit.data !== undefined) || credit.data !== null; 
     let creditLeadIDExists = (credit.data.LeadID !== undefined) || credit.data.LeadID !== null; 
     let creditHistoryExists = (creditDataExists && creditLeadIDExists); 
     this.isPostGA2 = (credit.loadComplete || creditHistoryExists); 
     }, 
     err => {} 
    ); 
    } 


} 

單元測試在這一點上是非常基本的。我檢查是否定義了CreditService。我的單元測試看起來如下:

import { fakeAsync, inject, TestBed } from '@angular/core/testing'; 
import { DtmAppModule } from '../../modules/app.module'; 
import { configureTests } from '../../tests.configure'; 
import { CreditService } from './credit-service'; 
import {MockAppStateService} from '../../mock/service/app-state-service-mock'; 
import {MockPromiseService} from '../../mock/service/promise-service-mock'; 
import { AppStateService } from '../../services/app-state-service/app-state-service'; 
import { PromiseService } from '../../services/promise/promise-service'; 
import {NgRedux} from 'ng2-redux'; 


describe('Service: Credit',() => { 
    let creditService: CreditService = null; 

    beforeEach(done => { 
    const configure = (testBed: TestBed) => { 
     testBed.configureTestingModule({ 
     imports: [DtmAppModule], 
     providers: [ 
      { provide: AppStateService, useClass: MockAppStateService }, 
      { provide: PromiseService, useClass: MockPromiseService }, 
      { provide: NgRedux, useClass: NgRedux }, 
     ] 
     }); 
    }; 

    configureTests(configure).then(testBed => { 
     done(); 
    }); 
    }); 

    // Inject the service 
    beforeEach(inject([CreditService], (service: CreditService) => { 
    creditService = service; 
    })); 

    //Do a simple test 
    it('should have a defined service',() => { 
    expect(creditService).toBeDefined(false); 
    }); 
}); 

我在執行測試時遇到了異常(請參閱下文)。我相信這個例外是因爲我試圖在一個未定義的Redux存儲對象上執行一個'select'方法。

  • 我該如何解決基本的'toBeDefined'測試?
  • 我如何注入Rxjs模擬商店進行測試?
  • 有沒有辦法模擬從返回_credit $ Observable

我在執行測試時遇到異常(請參見下文)。我相信這個例外是未定義的Redux商店的'選擇'。

TypeError: Cannot read property 'select' of undefined 
     at CreditService.getter [as _credit$] (webpack:///~/ng2-redux/lib/decorators/select.js:23:0 <- src/tests.entry.ts:150235:47) 
     at CreditService.setupSubscriptionForPostGA2 (webpack:///src/services/credit/credit-service.ts:47:17 <- src/tests.entry.ts:24169:17) 
     at new CreditService (webpack:///src/services/credit/credit-service.ts:40:2 <- src/tests.entry.ts:24155:14) 
     at DynamicTestModuleInjector.get (DynamicTestModule.ngfactory.js:367:71) 
     at DynamicTestModuleInjector.getInternal (DynamicTestModule.ngfactory.js:638:53) 
     at DynamicTestModuleInjector.NgModuleInjector.get (webpack:///~/@angular/core/src/linker/ng_module_factory.js:94:0 <- src/tests.entry.ts:91283:27) 
     at TestBed.get (webpack:///~/@angular/core/bundles/core-testing.umd.js:1114:0 <- src/tests.entry.ts:9003:51) 
     at webpack:///~/@angular/core/bundles/core-testing.umd.js:1120:50 <- src/tests.entry.ts:9009:65 
     at Array.map (native) 
     at TestBed.execute (webpack:///~/@angular/core/bundles/core-testing.umd.js:1120:0 <- src/tests.entry.ts:9009:33) 
+0

你有沒有想辦法解決這個問題?我遇到了同樣的問題。 –

+0

仍在尋找答案 –

+0

我從裝飾器方法移到選擇ngRedux實例,現在我可以針對注入ngredux的組件運行單元測試。從\t @select(['board','ready'])只讀boardReady $:Observable ; to this.boardReady $ = this.ngRedux.select(['board','ready']);在ngOnInit()中 –

回答

2

您可以提供一個空的模擬類覆蓋選擇:

export class MockSelect { 
} 

,然後將其添加到您的供應商名單:

{provide: select, useClass: MockSelect} 

您可以在同一模擬出觀測方式:

export class MockObservable<T> { 
} 

然後根據單元測試需要自己設置值。