bin*_*tch 3 rxjs5 redux-observable
最近几天,我一直在使用rxjs和redux-observable,并且一直在努力寻找一种方法来测试Observable.ajax。我有以下史诗,它创建了对https://jsonplaceholder.typicode.com/的请求,
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))
)
}
Run Code Online (Sandbox Code Playgroud)
哪里,
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 }
}
Run Code Online (Sandbox Code Playgroud)
该代码在浏览器中运行时可以正常运行,但在使用Jest进行测试时则无法正常运行。
我尝试过
1)根据https://redux-observable.js.org/docs/recipes/WritingTests.html创建测试。store.getActions()仅返回{类型: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 }
])
})
})
Run Code Online (Sandbox Code Playgroud)
2)根据Redux-observable创建测试:史诗级的开玩笑测试失败。它返回
超时-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()
})
})
Run Code Online (Sandbox Code Playgroud)
有人可以指出我测试Observable.ajax的正确方法是什么?
我将遵循来自StackOverflow的第二个示例。要使其正常工作,您需要进行一些小的调整。无需导入Observable.ajax史诗文件并直接使用该引用,而是需要使用某种形式的依赖项注入。一种方法是在创建它时将其提供给中间件。
import { ajax } from 'rxjs/observable/dom/ajax';
const epicMiddleware = createEpicMiddleware(rootEpic, {
dependencies: { ajax }
});
Run Code Online (Sandbox Code Playgroud)
我们传递的对象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))
);
}
Run Code Online (Sandbox Code Playgroud)
另外,您不能使用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))
);
}
Run Code Online (Sandbox Code Playgroud)
无论您选择哪种方式,当我们测试史诗时,我们现在都可以直接调用它并为其提供自己的模拟。以下是成功/错误/取消路径的示例这些未经测试,可能会出现问题,但应为您提供一般思路
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();
}
});
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1397 次 |
| 最近记录: |