Desarrollo de un equipo para consultar datos de la base de datos - parte 4, concluyendo

Esta es una continuación de la historia que comenzó aquí y continuó aquí y aquí .


En la última parte, escribí una prueba de integración que demuestra el proceso de inicialización y ejecución de un conjunto completo de controladores que extraen datos de una base de datos. Pero dado que puede llevar demasiado tiempo escribir esta prueba para ejecutarla, necesaria para codificar no solo el controlador, sino también las reglas de configuración para todas las consultas necesarias en la base de datos, hoy decidí implementar su versión modular, diseñada para configurar y ejecutar todo un manejador Esta prueba se ve así:


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(); } }); 

Ejecuto las pruebas y recibo un mensaje de que no se encontró el módulo con las reglas. Una vez más, ¿qué necesitará extraer el controlador de las reglas?


  1. El nombre de la clave de propiedad del contenedor de propiedades a la que se vinculará el registro recibido de la base de datos.
  2. El nombre de la tabla de la base de datos de la que desea extraer el registro.
  3. El método que forma la solicitud que deberá enviarse a la base de datos para obtener una respuesta
  4. El método del despachador que envía el registro recibido de la base de datos al almacén de contenedores del estado.
  5. Un método de envío que envía un error, si lo hay, al almacenamiento del contenedor de estado. Decidí primero consolidar los errores en el contenedor de estado y luego tratarlos.

El conjunto de reglas me parece un diccionario ( Map ), en el que la clave será el nombre de la propiedad del contenedor de estado y probablemente formularé la primera prueba unitaria:


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

Ejecuté las pruebas y Jasmine me dice que ahora tengo dos pruebas fallidas. Para no complicar la tarea, comenzaré con una regla simple que me dice que para asignar un valor a la clave de user del contenedor de estado, mi solicitud debe ir a la tabla de users para obtener datos. Todo parece ser lógico. Escribiré como me parece un pequeño código.


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

Ejecuto las pruebas y veo que solo la prueba de mi controlador falla, aunque el error ahora es diferente. Sin embargo, volveré a esta prueba más tarde, cuando tenga al menos una regla completa en mi diccionario lista.


Modificaré un poco la prueba del diccionario de reglas. Agregaré un código que verifica la presencia de un método de despachador que maneja un error al ejecutar una consulta a la base de datos:


 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'); }); }); 

Ejecuto las pruebas, me aseguro de volver a tener dos pruebas fallidas y vuelvo a finalizar el código del método de fábrica para generar el diccionario de reglas. Agrego la función al objeto literal de la primera regla:


 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(); 

Ejecutando las pruebas nuevamente. El nuevo fragmento de regla pasa la prueba con éxito, por lo que decido agregar comprobaciones para todas las reglas restantes:


 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'); }); }); 

Corro pruebas. El conjunto de prueba para el diccionario de reglas nuevamente arroja un error. Estoy escribiendo el código:


 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(); 

Corro pruebas. La prueba del conjunto de reglas nuevamente se realiza con éxito, y me parece que ahora puedo comenzar a escribir código para la versión realmente nueva de solicitar datos de la base de datos. Esta vez no usaré la sintaxis de la clase, porque no veo ninguna ventaja de su uso. Habrá mucho código a la vez, porque copio sin piedad la parte probada de la implementación de la solicitud existente, completándola con una verificación, en caso de que el registro de la base de datos ya se haya extraído y colocado en el contenedor de estado. Entonces el código:


 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; 

Ejecución de pruebas ... tambor roll! Y veo una línea de puntos verdes. Todas las pruebas se completaron con éxito. Y, por lo tanto, agregaré otra prueba al conjunto que verifica la corrección del manejo de errores, hasta que haya olvidado que para que mi pseudo- DbMock devuelva un error, necesito pedirle una entrada con Id igual a 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(); } 

Corro las pruebas de nuevo. Todo funciona como se esperaba. Podemos suponer que el prototipo correcto del comando de consulta a la base de datos está listo y volver a refactorizar y desarrollar las reglas para configurar consultas, porque ahora está claro que el código para generar el conjunto de reglas dejará de ser legible después de agregar solo un par de reglas más en el mismo formato.

Source: https://habr.com/ru/post/es436654/


All Articles