这是我在Mocha / Chai中编写的测试存根。我可以轻松地调度一个动作并断言状态等于我的期望,但是如何验证它是否遵循了预期的过程(IE早期的测试)?
/**
* This test describes the INITIALIZE_STATE action.
* The action is asynchronous using the async/await pattern to query
* The database. The action creator returns a thunk which should in turn
* return the new state with a list of tables and their relationships with eachother
**/
describe('Initialize state', () => {
it('Should check if state is empty', () => {});
it('Should check if tables/relationships exist', () => {});
it('Should check if new tables have been added', () => {});
it('Should merge new and existing tables and relationships', () => {
// Here is where we would dispatch the INITIALIZE_STATE
// action and assert that the new state is what I expect it to be.
});
});
我还没有为实际操作本身编写任何代码,因为我希望代码能够通过这些验证。一些伪代码可能看起来像这样
export function initializeState() {
return function(dispatch) {
let empty = store.getState().empty
let state = (empty) ? await getLastPersistedState() : store.getState()
let tables = state.tables;
let payload = tables.concat(await getNewTables(tables));
dispatch({type: 'INITIALIZE_STATE', payload});
}
}
function getLastPerisistedState() {
return mongodb.findall(state, (s) => s);
}
function getNewTables(tableFilter) {
return sql.query("select table_name from tables where table_name not in (" + tableFilter + ")");
}
答案 0 :(得分:0)
这是我提出的解决方案。可能有一个更好的,但到目前为止还没有人能够提供一个。我决定采用重构的一系列操作和一个单独的商店进行测试。这些动作是函数生成器而不是使用thunk。它们会产生thunk将在生产代码中分派的操作。在我的测试中,我可以自己发送这些动作,并验证结果状态是我所期望的。这正是thunk将要做的事情,但它允许我插入自己作为中间人,而不是依赖于thunk中间件。
这也非常有用,因为它使得动作逻辑与调度和状态逻辑分离非常容易,即使在测试异步流时也是如此。
对于数据库,我自动生成存根并使用promises来模拟异步查询。由于这个项目无论如何都在使用sequelize,我只是使用sequelize来生成存根。
这是代码
<强> _actions.js 强>
export function *initializeState() {
//We will yield the current step so that we can test it step by step
//Should check if state is empty
yield {type: 'UPDATE_STEP', payload: 'IS_STATE_EMPTY'};
yield {type: 'UPDATE_STEP_RESULT', payload: stateIsEmpty()};
if(stateIsEmpty()) {
//todo: Implement branch logic if state is empty
}
//...
}
<强> sequelize / _test / generate.js 强>
async function createMockFromSql(db, sql, filename) {
let results = await db.query(sql, {type: db.Sequelize.QueryTypes.SELECT});
return new Promise((resolve, reject) => {
// Trim the results to a reasonable size. Keep it unique each time
// for more rigorous testing
console.log('trimming result set');
while (results.length > 50) {
results.splice(results.length * Math.random() | 0, 1);
}
fs.writeFile(path.resolve(__dirname, '../../sequelize/_test', filename), JSON.stringify(results, null, 2), err => {
if (err) {
console.error(err);
reject(false);
}
resolve(true);
})
})
}
<强>测试/ actions.js 强>
...
it('Should check if state is empty', () => {
let action = initializeState();
expect(action.next()).to.deep.equal({type: 'UPDATE_STEP', payload: 'IS_STATE_EMPTY'})
});