开发一个用于从数据库查询数据的团队-第4部分,总结

这是从这里开始的故事的延续,并在这里这里继续。


在最后一部分中,我编写了一个集成测试,演示了初始化和执行从数据库提取数据的完整处理程序集的过程。 但是由于从编写该测试到运行它可能需要很长时间,因此不仅需要对处理程序进行编码,而且还要对数据库进行所有必要查询的配置规则进行编码,所以今天我决定实现其模块化版本,该版本旨在配置和运行所有内容一个处理程序。 该测试如下所示:


describe('requestHandler', () => { const createStore = require('redux').createStore; const reducers = require('../../src/reducers.js'); const DbMock = require('../mocks/DbMock'); const db = new DbMock(); const rules = require('../../src/rules'); const dbRequest = require('../../src/storage/dbRequest'); let request = null, store = null, context = null; beforeEach(() => { store = createStore(reducers); context = { db, store, rules }; request = dbRequest.bind(context, [ 'user' ]); expect(store.getState().user).toBeNull(); expect(store.getState().error).toEqual([]); }); it('should get user from database', (done) => { const assert = checkUser.bind(context, [ done ]); store.subscribe(assert); store.dispatch({type: 'NOTE', note: { Id: 1, UserRecordId: 1 }}); request(); }); function checkUser(args) { const state = store.getState(); if(state.user === null) return; const user = state.user; expect(user.Id).toEqual(1); expect(user.Name).toEqual('Jack'); const checkIsCompleted = args[0]; checkIsCompleted(); } }); 

我运行测试并收到一条消息,指出未找到带有规则的模块。 再次,处理程序需要从规则中提取什么?


  1. 从数据库接收到的记录将绑定到的属性容器属性键的名称
  2. 您要从中提取记录的数据库表的名称
  3. 形成请求的方法,需要将其发送到数据库以获取响应
  4. 将从数据库接收的记录发送到状态容器存储的调度程序方法。
  5. 将错误(如果有)发送到状态容器存储的调度方法。 我决定先将错误合并到状态容器中,然后再进行处理。

在我看来,规则集是一个字典( Map ),其中的键将是状态容器的属性的名称,并且我可能会制定第一个单元测试:


 describe('rules', () => { const rules = require('../src/rules'); it('should contain user rules', () => { const rule = rules.get('user'); expect(rule.table).toEqual('users'); }); }); 

我运行测试, Jasmine告诉我,现在我有两个失败的测试。 为了不使任务复杂化,我将从一条简单的规则开始,该规则告诉我要为状态容器的user键分配一个值,我的查询应转到users表以获取数据。 一切似乎都是合乎逻辑的。 在我看来,我将编写一些代码。


 const makeRules = () => { const rules = new Map(); rules.set('user', { table: 'users' }); return rules; }; module.exports = makeRules(); 

我运行了测试,尽管错误现在有所不同,但我看到只有我的处理程序的测试崩溃了。 但是,当我准备好字典中的至少一条完整规则时,我将稍后返回此测试。


我将修改规则字典测试。 我将添加一个代码,检查是否存在处理在执行数据库查询中的错误的调度程序方法:


 describe('rules', () => { const rules = require('../src/rules'); it('should contain user rules', () => { const rule = rules.get('user'); expect(rule.table).toEqual('users'); expect(rule.onError.name).toEqual('dispatchError'); expect(typeof rule.onError).toEqual('function'); }); }); 

我运行测试,确保再次有两个失败的测试,然后返回完成工厂方法代码的生成以生成规则字典。 我将函数添加到第一条规则的对象文字中:


 const makeRules = () => { const rules = new Map(); rules.set('user', { table: 'users', onError: function dispatchError(error, store) { const action = { type: 'ERROR', error }; store.dispatch(action); } }); return rules; }; module.exports = makeRules(); 

再次运行测试。 新的规则片段成功通过了测试,因此我决定为所有其余规则添加检查:


 describe('rules', () => { const rules = require('../src/rules'); it('should contain user rules', () => { const rule = rules.get('user'); expect(rule.table).toEqual('users'); expect(rule.onError.name).toEqual('dispatchError'); expect(typeof rule.onError).toEqual('function'); expect(rule.onSuccess.name).toEqual('dispatchUser'); expect(typeof rule.onSuccess).toEqual('function'); expect(rule.query.name).toEqual('getUserQuery'); expect(typeof rule.query).toEqual('function'); }); }); 

我进行测试。 规则字典的测试集再次引发错误。 我正在编写代码:


 const makeRules = () => { const rules = new Map(); rules.set('user', { table: 'users', onError: function dispatchError(error, store) { const action = { type: 'ERROR', error }; store.dispatch(action); }, onSuccess: function dispatchUser(user, store) { const action = { type: 'USER', user }; store.dispatch(action); }, query: function getUserQuery(store) { const state = store.getState(); if(state.note === null) return null; return { Id: state.note.UserRecordId }; } }); return rules; }; module.exports = makeRules(); 

我进行测试。 规则集的测试再次成功执行,在我看来,我现在可以开始为从数据库请求数据的实际新版本编写代码。 这次我将不使用类语法,因为使用它不会带来任何好处。 一次将有很多代码,因为如果已经从数据库中提取了记录并将其放置在状态容器中,那么我会从现有的请求实现中无情地复制被测试的部分,并用检查进行补充。 所以代码:


 function dbRequest(args){ const key = args[0]; const getQuery = this.rules.get(key).query; const dispatchUser = this.rules.get(key).onSuccess; const dispatchError = this.rules.get(key).onError; const tableName = this.rules.get(key).table; const table = this.db.Model.extend({ tableName: tableName }); const state = this.store.getState(); if(state[key] !== null) return; const query = getQuery(this.store); if(query === null) return; table.where(query).fetch().then((item) => { dispatchUser(item, this.store); }).catch((error) => { dispatchError(error, this.store); }); } module.exports = dbRequest; 

运行测试...鼓! 我看到一行绿色的圆点。 所有测试均成功完成。 因此,我将向集合中添加另一个测试以检查错误处理的正确性,直到我忘记了为了使我的伪DbMock返回错误,我需要向她输入Id等于555的条目:


 it('should add error in store state', (done) => { const assert = checkErrorHasBeenAdded.bind(context, [ done ]); store.subscribe(assert); store.dispatch({type: 'NOTE', note: { Id: 1, UserRecordId: 555 }}); request(); }); function checkErrorHasBeenAdded(args){ const state = store.getState(); if(state.error.length === 0) return; const error = state.error; expect(Array.isArray(error)).toBeTruthy(); expect(error.length).toEqual(1); expect(error[0].message).toEqual('Something goes wrong!'); const checkIsCompleted = args[0]; checkIsCompleted(); } 

我再次运行测试。 一切正常。 我们可以假设数据库查询命令的正确原型已经准备就绪,可以返回重构和开发配置查询的规则,因为现在很明显,在仅添加了几条相同格式的规则后,生成规则集的代码将不再可读。

Source: https://habr.com/ru/post/zh-CN436654/


All Articles