testing - Redux-observable 测试和丢失我的 Marbles
问题描述
我想测试这个 observable 但我什么也没得到:
const fetchUsersApi = (action$: any) => action$.pipe(
ofType(FETCH_USERS),
mergeMap(() => from(
API.graphql(graphqlOperation(queries.LIST_ALL_USERS)),
).pipe(
map((res: any) => fetchUsersSuccess(
// TODO - standardise this to 'items' so fetchApi can be used
pathOr(null, ['data', 'listAllUsers', 'users'], res),
)),
catchError((error: Error) => {
const processedError = processAppSyncErrorMessage(error);
console.log('Error', processedError);
return of(addError(processedError), fetchUsersError(processedError));
}),
)),
);
测试如下:
import { TestScheduler } from 'rxjs/testing';
import { API } from 'aws-amplify';
import { ActionsObservable } from 'redux-observable';
import { fetchUsersSuccess, fetchUsers } from '../actions';
import fetchUsersEpic from './fetchUsersApi';
jest.mock('aws-amplify');
const testScheduler = new TestScheduler(
(actual, expected) => expect(actual).toStrictEqual(expected),
);
describe('fetchUsersEpic', () => {
it('should fetch the users', () => {
const mockFetchedUsers = [
{ id: 'fakeUser1' },
];
(API.graphql as jest.Mock).mockImplementation(() => Promise.resolve({
data: { listAllUsers: { users: mockFetchedUsers } },
}));
testScheduler.run((helpers) => {
const {
hot,
cold,
expectObservable,
flush,
} = helpers;
const action$ = cold('-a', {
a: fetchUsers(),
});
const reduxObservableaAction = ActionsObservable.from(action$);
const actual = fetchUsersEpic(reduxObservableaAction);
const expectedMarbles = '-b';
const expectedValues = { b: fetchUsersSuccess(mockFetchedUsers) };
expectObservable(actual).toBe(expectedMarbles, expectedValues);
flush();
});
});
});
我得到的结果是:
● fetchUsersEpic › 应该获取用户
expect(received).toStrictEqual(expected) // 深度相等
- 预计 - 18
- 收到 + 1
显然我在这里遗漏了一些东西,我认为返回的值应该是带有一些数据的 fetchUsersSuccess() 回调,但我们得到的是一个空数组。能得到一些想法会很棒。
解决方案
我决定忽略提供的测试解决方案,对整个商店进行测试。它工作得更好,如果我们决定 bin redux-observable,我们仍然可以保留测试。
import {
applyMiddleware, createStore, Action,
} from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension';
import { createEpicMiddleware, combineEpics, Epic } from 'redux-observable';
import rootReducer from '../../store/reducers';
/**
* makeActionListMiddleware is a function to allow us to pass a jest mock
* function to the store to pick up on any actions that are called on it
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const makeActionMiddleware = (jestMockFunction: jest.Mock) => (store: object) => (next: any) => (action: Action<any>) => {
jestMockFunction(action);
// continue to the next action
return next(action);
};
// creates a fake version of the store with selected epics combined and a jest
// function middleware that received all store events.
const createEpicTester = (
epics: Epic[],
reducers = rootReducer,
initialState = {},
) => {
const storeActionJestCallback = jest.fn();
const jestActionMiddleware = makeActionMiddleware(storeActionJestCallback);
const composeEnhancers = composeWithDevTools({});
const epicMiddleware = createEpicMiddleware();
const store = createStore(reducers, initialState, composeEnhancers(
applyMiddleware(epicMiddleware, jestActionMiddleware),
));
epicMiddleware.run(combineEpics(...epics));
return { store, dispatch: store.dispatch, storeActionJestCallback };
};
export default createEpicTester;
用法
const { dispatch, storeActionJestCallback } = createEpicTester([epic]);
dispatch({ type: "someEvent" });
expect(storeActionJestCallback).toHaveBeenCalledWith({ type: "someEvent" });
您现在可以期待您的史诗应用到商店的更多事件。
推荐阅读
- python - 如何获取一个包含值和标题表的 .txt 文件并将其转换为 numpy 2D 数组?
- r - 宽到长和列名到行名
- python - 使用“稀疏分类交叉熵”
- java - Mokito 注释 @Mock,@InjectMocks 不起作用
- python - 如何根据值替换行数据
- unity3d - Unity 3D:什么可能导致旋转小工具偏离游戏对象中心?
- flutter - 使用 onTapLink 时出错:无法分配参数类型'void Function(String, String, String)'
- php - 如果请求来自不同的来源,是否可以拥有会话/cookie?
- java - 试图从索引表中获取数据会产生 -java.lang.NoSuchMethodError: org.hibernate.query.internal.ParameterMetadataImpl
- c# - C#:如何使用 Microsoft Graph API 强制用户满载?