Javascript 如何对这个Redux thunk进行单元测试?
因此,我有一个Redux操作创建者,它使用Javascript 如何对这个Redux thunk进行单元测试?,javascript,redux,chai,Javascript,Redux,Chai,因此,我有一个Redux操作创建者,它使用Redux thunk中间件: accountDetailsActions.js: export function updateProduct(product) { return (dispatch, getState) => { const { accountDetails } = getState(); dispatch({ type: types.UPDATE_PRODUCT, stateOfRe
Redux thunk
中间件:
accountDetailsActions.js:
export function updateProduct(product) {
return (dispatch, getState) => {
const { accountDetails } = getState();
dispatch({
type: types.UPDATE_PRODUCT,
stateOfResidence: accountDetails.stateOfResidence,
product,
});
};
}
describe('types.UPDATE_PRODUCT', () => {
it('should update product when passed a product object', () => {
//arrange
const initialState = {
product: {}
};
const product = {
id: 1,
accountTypeId: 1,
officeRangeId: 1,
additionalInfo: "",
enabled: true
};
const action = actions.updateProduct(product);
const store = mockStore({courses: []}, action);
store.dispatch(action);
//this is as far as I've gotten - how can I populate my newState variable in order to test the `product` field after running the thunk?
//act
const newState = accountDetailsReducer(initialState, action);
//assert
expect(newState.product).to.be.an('object');
expect(newState.product).to.equal(product);
});
});
如何测试它?我正在使用chai
包进行测试。我在网上找到了一些资源,但不确定如何继续。以下是我目前的测试:
accountDetailsReducer.test.js:
export function updateProduct(product) {
return (dispatch, getState) => {
const { accountDetails } = getState();
dispatch({
type: types.UPDATE_PRODUCT,
stateOfResidence: accountDetails.stateOfResidence,
product,
});
};
}
describe('types.UPDATE_PRODUCT', () => {
it('should update product when passed a product object', () => {
//arrange
const initialState = {
product: {}
};
const product = {
id: 1,
accountTypeId: 1,
officeRangeId: 1,
additionalInfo: "",
enabled: true
};
const action = actions.updateProduct(product);
const store = mockStore({courses: []}, action);
store.dispatch(action);
//this is as far as I've gotten - how can I populate my newState variable in order to test the `product` field after running the thunk?
//act
const newState = accountDetailsReducer(initialState, action);
//assert
expect(newState.product).to.be.an('object');
expect(newState.product).to.equal(product);
});
});
我的thunk不执行任何异步操作。有什么建议吗?看看官方文件。另外,你在测试什么,动作创建者还是减速器
ActionCreator测试示例
减速器测试示例
您的reducer应该是一个纯函数,因此您可以在存储环境之外单独测试它
const yourReducer = require('../reducers/your-reducer');
describe('reducer test', () => {
it('should do things', () => {
const initialState = {
product: {}
};
const action = {
type: types.UPDATE_PRODUCT,
stateOfResidence: // whatever values you want to test with,
product: {
id: 1,
accountTypeId: 1,
officeRangeId: 1,
additionalInfo: "",
enabled: true
}
}
const nextState = yourReducer(initialState, action);
expect(nextState).to.be.eql({ /* ... */ });
});
});
如何单元测试Redux Thunks thunk动作创建者的全部目的是在将来分派异步动作。当使用redux thunk时,一个好的方法是对开始和结束的异步流进行建模,从而通过三个操作获得成功或错误 尽管本例使用Mocha和Chai进行测试,但您也可以很容易地使用任何断言库或测试框架 使用我们的主要thunk action创建者管理的多个操作对异步流程进行建模 为了这个例子,让我们假设您想要执行一个异步操作来更新产品,并且想要知道三件关键的事情
- 异步操作开始时
- 异步操作完成时
- 异步操作是否成功或失败
// This is only an example to create asynchronism and record time taken
function updateUser(){
return new Promise( // Returns a promise will be fulfilled after a random interval
function(resolve, reject) {
window.setTimeout(
function() {
// We fulfill the promise with the time taken to fulfill
resolve(thisPromiseCount);
}, Math.random() * 2000 + 1000);
}
)
})
我们的测试文件
import configureMockStore from 'redux-mock-store'
import thunk from 'redux-thunk'
import chai from 'chai' // You can use any testing library
let expect = chai.expect;
import { updateProduct } from './accountDetailsActions.js'
const middlewares = [ thunk ]
const mockStore = configureMockStore(middlewares)
describe('Test thunk action creator', () => {
it('expected actions should be dispatched on successful request', () => {
const store = mockStore({})
const expectedActions = [
'updateProductStarted',
'updateProductSuccessful'
]
return store.dispatch(fetchSomething())
.then(() => {
const actualActions = store.getActions().map(action => action.type)
expect(actualActions).to.eql(expectedActions)
})
})
it('expected actions should be dispatched on failed request', () => {
const store = mockStore({})
const expectedActions = [
'updateProductStarted',
'updateProductFailure'
]
return store.dispatch(fetchSomething())
.then(() => {
const actualActions = store.getActions().map(action => action.type)
expect(actualActions).to.eql(expectedActions)
})
})
})
在Reducer测试示例中,您手动创建action对象,而在我的测试中,我从action creator方法(
actions.updateProduct()
)获取操作。在测试减缩器时,哪种方法是更好的实践?我认为这取决于动作创建者的复杂性。如果它相当复杂(例如thunks),我建议创建如上所述的操作来关注减速器逻辑。当您的动作创建者仅仅返回一个对象时,我会按照您的建议内联创建它们。我总是建议使用最简单的解决方案,在思考事情是如何发生的方面不需要太多的开销(例如动作)。看看这个答案,它的结构非常好,但它不能测试动作创建者是否使用正确的参数被调用,对吗?你能看看这个吗?不会调用fetchMock.restore()
,因为您正在store.dispatch()
上执行return
?我刚刚在这里介绍了使用redux thunk测试操作的方法,就像在主题中一样。您好,请始终尝试解释您将来演示的任何代码。欢迎来到StackOverflow!
export const someAsyncAction = (param) => (dispatch, getState) => {
const { mock } = getState();
dispatch({
type: 'SOME_TYPE',
mock: mock + param,
})
}
it('should test someAsyncAction', () => {
const param = ' something';
const dispatch = jest.fn().mockImplementation();
const getState = () => ({
mock: 'mock value',
});
const expectedAction = {
type: 'SOME_TYPE',
mock: 'mock value something'
};
const callback = someAsyncAction(param);
expect(typeof callback).toBe('function');
callback.call(this, dispatch, getState);
expect(dispatch.mock.calls[0]).toEqual([expectedAction])
});