2017-09-26 5 views
2

나는 지난 며칠 동안 rxjs와 redux-observable을 가지고 놀았으며 Observable.ajax에 대한 테스트 방법을 찾기 위해 애썼다. 나는 브라우저에서 실행되지만이 농담으로 테스트하지 않을 경우 때 코드가 잘 작동Observable.ajax (redux-observable)는 어떻게 테스트 할 수 있습니까?

export function testApiEpic (action$) { 
    return action$.ofType(REQUEST) 
    .switchMap(action => 
     Observable.ajax({ url, method }) 
     .map(data => successTestApi(data.response)) 
     .catch(error => failureTestApi(error)) 
     .takeUntil(action$.ofType(CLEAR)) 
    ) 
} 

,

export const REQUEST = 'my-app/testApi/REQUEST' 
export const SUCCESS = 'my-app/testApi/SUCCESS' 
export const FAILURE = 'my-app/testApi/FAILURE' 
export const CLEAR = 'my-app/testApi/CLEAR' 

export function requestTestApi() { 
    return { type: REQUEST } 
} 
export function successTestApi (response) { 
    return { type: SUCCESS, response } 
} 
export function failureTestApi (error) { 
    return { type: FAILURE, error } 
} 
export function clearTestApi() { 
    return { type: CLEAR } 
} 

https://jsonplaceholder.typicode.com/에 요청을 만들려면 다음 서사시를 가지고있다. 내가 시도가

,

1) https://redux-observable.js.org/docs/recipes/WritingTests.html에 따라 검사를 만듭니다. store.getActions()는 {type : REQUEST} 만 반환합니다.

const epicMiddleware = createEpicMiddleware(testApiEpic) 
const mockStore = configureMockStore([epicMiddleware]) 

describe.only('fetchUserEpic',() => { 
    let store 

    beforeEach(() => { 
    store = mockStore() 
    }) 

    afterEach(() => { 
    epicMiddleware.replaceEpic(testApiEpic) 
    }) 

    it('returns a response,() => { 
    store.dispatch({ type: REQUEST }) 
    expect(store.getActions()).toEqual([ 
     { type: REQUEST }, 
     { type: SUCCESS, response } 
    ]) 
    }) 
}) 

2) Redux-observable: failed jest test for epic을 기반으로 테스트를 만듭니다.

과 함께 반환됩니다. 시간 초과 - jasmine.DEFAULT_TIMEOUT_INTERVAL에 지정된 제한 시간 내에 비동기 콜백이 호출되지 않았습니다.

it('returns a response', (done) => { 
    const action$ = ActionsObservable.of({ type: REQUEST }) 
    const store = { getState:() => {} } 
    testApiEpic(action$, store) 
     .toArray() 
     .subscribe(actions => { 
     expect(actions).to.deep.equal([ 
      { type: SUCCESS, response } 
     ]) 
     done() 
     }) 
    }) 

사람은 Observable.ajax을 테스트하는 올바른 방법이 무엇인지 저를 지적 할 수 있습니까?

답변

2

두 번째 예제는 StackOverflow에서 따릅니다. 작동 시키려면 약간의 조정이 필요할 것입니다. 서사 파일에 Observable.ajax을 가져 오지 않고 해당 참조를 직접 사용하는 대신 어떤 형태의 의존성 주입을 사용해야합니다. 한 가지 방법은 미들웨어를 만들 때 미들웨어에 제공하는 것입니다.

import { ajax } from 'rxjs/observable/dom/ajax'; 

const epicMiddleware = createEpicMiddleware(rootEpic, { 
    dependencies: { ajax } 
}); 

우리가 dependencies로 전달 목적은

export function testApiEpic (action$, store, { ajax }) { 
    return action$.ofType(REQUEST) 
    .switchMap(action => 
     ajax({ url, method }) 
     .map(data => successTestApi(data.response)) 
     .catch(error => failureTestApi(error)) 
     .takeUntil(action$.ofType(CLEAR)) 
    ); 
} 

또는 세 번째 인수로 모든 서사시로 제공 될 것입니다, 당신은 미들웨어의 dependencies 옵션을 사용하고 대신 기본 매개 변수를 사용할 수 없습니다 :

export function testApiEpic (action$, store, ajax = Observable.ajax) { 
    return action$.ofType(REQUEST) 
    .switchMap(action => 
     ajax({ url, method }) 
     .map(data => successTestApi(data.response)) 
     .catch(error => failureTestApi(error)) 
     .takeUntil(action$.ofType(CLEAR)) 
    ); 
} 

우리가 서사시를 테스트 할 때 우리는 이제 그것을 직접 호출 할 수 있으며 우리 자신의 모의를 제공 할 수 있습니다. 여기에 성공/오류/경로를 다음은 테스트되지 을 취소하고 문제가있을 수 있습니다에 대한 예입니다,하지만 당신은 일반적인 생각

it('handles success path', (done) => { 
    const action$ = ActionsObservable.of(requestTestApi()) 
    const store = null; // not used by epic 
    const dependencies = { 
    ajax: (url, method) => Observable.of({ url, method }) 
    }; 

    testApiEpic(action$, store, dependencies) 
    .toArray() 
    .subscribe(actions => { 
     expect(actions).to.deep.equal([ 
     successTestApi({ url: '/whatever-it-is', method: 'WHATEVERITIS' }) 
     ]) 

     done(); 
    }); 
}); 

it('handles error path', (done) => { 
    const action$ = ActionsObservable.of(requestTestApi()) 
    const store = null; // not used by epic 
    const dependencies = { 
    ajax: (url, method) => Observable.throw({ url, method }) 
    }; 

    testApiEpic(action$, store, dependencies) 
    .toArray() 
    .subscribe(actions => { 
     expect(actions).to.deep.equal([ 
     failureTestApi({ url: '/whatever-it-is', method: 'WHATEVERITIS' }) 
     ]) 

     done(); 
    }); 
}); 

it('supports cancellation', (done) => { 
    const action$ = ActionsObservable.of(requestTestApi(), clearTestApi()) 
    const store = null; // not used by epic 
    const dependencies = { 
    ajax: (url, method) => Observable.of({ url, method }).delay(100) 
    }; 
    const onNext = chai.spy(); 

    testApiEpic(action$, store, dependencies) 
    .toArray() 
    .subscribe({ 
     next: onNext, 
     complete:() => { 
     onNext.should.not.have.been.called();   
     done(); 
     } 
    }); 
}); 
을 제공한다