gpt4 book ai didi

javascript - 用于实例化单个对象,同时保持可测试性的模式

转载 作者:行者123 更新时间:2023-12-03 00:24:08 26 4
gpt4 key购买 nike

当我的应用程序启动时,它会实例化 Redis 客户端对象:

const redisClient = redis.createClient(REDIS_URL);

我维护一个代理对象 myRedisClient,它公开了客户端对象公开的 API 的 promise 版本:

const get = (key) => 
new Promise((resolve, reject) =>
redisClient.get(key, (err, resp) =>
err ? reject(err) : resolve(resp))

const myRedisClient = { get };

简单地隐式实例化redisClient感觉不对,所以我想将它放在一个显式调用的方法中:

let redisClient = null;
const init = () => redisClient || redis.createClient(REDIS_URL);
const myRedisClient = { init, get};

get 需要访问 redisClient。如果 getredisClient 变量位于同一个文件中,那么这很简单。

如果 get 位于单独的文件中,则可以通过关闭 redisClient 并将 redisClient 作为参数添加到获取

// my-redis-client.js
import get from './get';

let redisClient = null;
const init = () => redisClient || redis.createClient(REDIS_URL);
const myRedisClient = { init, get(key) => get(redisClient, key) };

// get.js
const get = (redisClient, key) =>
new Promise((resolve, reject) =>
redisClient.get(key, (err, resp) =>
err ? reject(err) : resolve(resp));

最后,我希望能够 stub redisClient,并且我想我可以 stub redis.createClient (例如,使用测试中内置的 stub 功能) runner),然后我从测试中调用它。

这个过程听起来合理吗?

最佳答案

It feels wrong to simply have redisClient implicitly instantiated

不,这没有什么问题,这正是您的应用在启动时应该执行的操作。

redisClient 的问题在于它是一个有状态的全局变量,并且您的 myRedisClient 隐式依赖它。将 redisClient 的初始化放在要显式调用的方法中并不能解决这两个问题。

能够删除 redisClient 之一

  • 通过在启动时安装 global.redisClient = ... 来明确它是一个全局变量。对于模拟,您可以轻松覆盖全局(如果您不想使用独立模拟并行运行多个测试)。
  • 明确依赖性并
    • 使用模块系统,其中 myRedisClient.js 依赖于导出“全局”静态值的 redisClient.js 模块,但让您的测试系统使用模块加载器使用依赖注入(inject)
    • 为您的 myRedisClient 创建一个构造函数或工厂函数,以便您可以通过显式地将 redisClient 传递给它来初始化它。

最后一个解决方案似乎符合您想要做的事情的精神。它应该看起来像这样:

// my-redis-client.js
default export function init(redisClient) {
const get = util.promisify(redisClient.get).bind(redisClient);

return { get };
}
// main.js
import initMyClient from 'my-redis-client'
const myRedisClient = initMyClient(redis.createClient(REDIS_URL));

关于javascript - 用于实例化单个对象,同时保持可测试性的模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54163323/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com