2017-04-04 4 views
2

단위 테스트를하고 싶습니다. 내 구성 요소에서 내 저장소를 업데이트하기 위해 @ ngrx/store 및 rxjs를 사용하고 있습니다. 그렇게하기 위해 상점을 구독하고 탈퇴합니다. 내 단위 테스트는 내가 제대로 내 가게와 이벤트 이미 터를 조롱하는 방법을 찾을 수 없습니다입니다@ ngrx/store를 조롱하는 방법?

TypeError: undefined is not an object (evaluating 'this.store.unsubscribe') in config/spec-bundle.js

와 함께 실패합니다.

app.component.ts :

ngOnDestroy() { 
    // unsubscribe the observable 
    this.userStore.unsubscribe(); 
    } 

app.component.spec.ts :

여기에 다음 줄 수 있습니다

 export class MockStore extends Subject<fromRoot.State> implements Store <fromRoot.State> {} 
: 나는 가게를 조롱하는 방법

구성 방법 :

 TestBed.configureTestingModule({ 
     imports: [ 
      FormsModule, 
      ReactiveFormsModule, 
      StoreModule.provideStore(reducer) 
     ], 
     declarations: [LoginComponent], 
     providers: [ 
      BaseRequestOptions, 
      MockBackend, 
      { provide: AuthService, useValue: authServiceStub }, 
      { provide: LoginService, useValue: loginServiceStub }, 
      { provide: LoggerService, useValue: loggerServiceStub }, 
      { 
       provide: Http, useFactory: (backend: ConnectionBackend, 
        defaultOptions: BaseRequestOptions) => { 
        return new Http(backend, defaultOptions); 
       }, deps: [MockBackend, BaseRequestOptions] 
      }, 
      { provide: Router, useClass: MockRouter } 
     ] 
    }) 

자세한 정보가 필요하면 알려주십시오. 미리 감사드립니다.

답변

5

상점을 조롱 할 수있는 방법은 여러 가지가 있으며 테스트하는 방법에 따라 다릅니다. 내 테스트에서 가게를 조롱 할 때

, 나는 두 가지 일에만 관심이있어 :

  • 쉽게 시험 관련이 상태를 방출 할 수있는; 및
  • 나는 그들이 다른 곳에서 테스트로, 감속기를 배선에 관심이없는 해요 test.the

동안 가게에 파견 된 모든 작업을 볼 수있는, 그래서 이것은 내가 할 것입니다.

은 내가 StoreSubject 두에서 인스턴스 생성과 같은 기능을 사용

import { Action, Store } from "@ngrx/store"; 
import { Subject } from "rxjs/Subject"; 

export function mockStore<T>({ 
    actions = new Subject<Action>(), 
    states = new Subject<T>() 
}: { 
    actions?: Subject<Action>, 
    states?: Subject<T> 
}): Store<T> { 

    let result = states as any; 
    result.dispatch = (action: Action) => actions.next(action); 
    return result; 
} 

그리고 beforeEach에서 나는 Store를 만들고에 추가를 TestBedproviders :

actions = new Subject<Action>(); 
states = new Subject<AppState>(); 
store = mockStore<AppState>({ actions, states }); 

TestBed.configureTestingModule({ 
    imports: [EffectsTestingModule], 
    providers: [ 
    { 
     provide: Store, 
     useValue: store 
    }, 
    ... 
    ] 
}); 

조롱 된 Store을 구성 요소 나 효과에 주입하거나 테스트하는 모든 것을 테스트 한 다음 특정 상태를 방출하는 것은 간단합니다. - states 제목을 사용하고 - actions 제목을 구독하여 예상되는 작업이 발송되었는지 쉽게 확인할 수 있습니다.

오류와 관련하여 Store에서 unsubscribe을 호출하면 안됩니다. 상점에 가입 할 때 반환되는 Subscription 개체에서 호출해야합니다 (다른 답변에서 언급했듯이).

+0

답변 해 주셔서 감사합니다. 나는 당신이하는 방법을 시도했지만 여전히 오류가 있습니다 ... 제가 다른 대답에서 말했듯이, 저는 이미 Subscription 객체에 대해 수신 거부를합니다. – Megan

1

문제는 수신 거부 될 수 있습니다. 관측 가능/저장 대신 구독을 실제로 취소해야합니다. 예. 이 같은 가입이있는 경우 : 당신은 몇 가지 코드를 왼쪽 있는지 확실하지 않습니다, 또한

ngOnDestroy() { 
    // unsubscribe the observable 
    this.subscription.unsubscribe(); 
    } 

,하지만 당신은 당신의 가게를 조롱하는 방식은, 아마 것 :

this.subscription = this._store 
    .select('users') 
    .subscribe(users => { 
     this.users = users; 
    }); 

당신은 다음과 같이 취소 실제 상점을 사용하기에 충분하며 파견에 대한 스파이 일뿐입니다.

+1

답변 주셔서 감사합니다 :) 일부 코드는 제 구성 요소로 제외되어 테스트가 정말 중요합니다. 나는 당신이 당신의 코멘트에 묘사 할 때 이미 탈퇴했다, 그래서 나는 다른 곳에서 나의 실수가 궁금하다 ... 'this.userStore = this.store.let (fromRoot.get) .subscribe ((state : any) => {//연결하면 환영 페이지로 이동}}; ' – Megan