背景
在处理多单元部署业务时,涉及到上层业务在region A调用导出接口,然后在region B中调用导入接口,把region A导出的数据导入。
在本地测试时,通过主备两套数据库来模拟。
跑单测时如果使用主数据库会造成大量脏数据,使用备数据库可以减少单测跑完后清理主数据库的麻烦。
如果按照正常流程,我们要从主库导入,然后再改改代码,然后再导入备用库。这里我们用Proxy来规避这种麻烦,在单测中一次性完成。
使用
数据库配置
修改config.local.js
:
...
knex: {
clients: {
db1: {
.... // 主数据库配置
},
db2: {
... // 备数据库配置
},
},
// 是否加载到 app 上,默认开启
app: true,
// 是否加载到 agent 上,默认关闭
agent: false,
},
...
挂载到Context
修改app/extend/context.js
:
// ...
get db1() {
return this.knex.get('db1');
}
get db2() {
return this.knex.get('db2');
}
// ...
业务
// app/service/multi_region_deployments.js
* importApp(info) {
// ...
yield this.ctx.db1('app').insert(info);
// ...
}
单测用例
// test/service/multi_region_deployments.test.js
// ...
describe('importApp()', () => {
beforeEach(() => {
ctx = app.mockContext();
});
it('should insert app info', function* () {
// 从主数据库中导出数据
const appInfo = yield ctx.service.multiRegionDeployments.exportApp(appId);
// 通过 Proxy 将 ctx.db1 代理为 ctx.db2, 无须改变业务代码
ctx.service.multiRegionDeployments.ctx = new Proxy(ctx.service.multiRegionDeployments.ctx, {
get(target, property) {
if (property === 'db1') {
return Reflect.get(target, 'db2');
}
return Reflect.get(target, property);
},
});
// 数据导入备数据库
const importAppRes = yield ctx.service.multiRegionDeployments.importApp(appInfo);
// assert something for importAppRes
// 清理备数据库
});
});
// ...