【问题标题】:How to test this dependancy?如何测试这种依赖关系?
【发布时间】:2018-06-20 16:25:33
【问题描述】:

背景

我正在尝试测试一个简单的缓存模块,但我看不到在注入依赖项时保持 API 不变的方法。

代码

const myCache = () => {
    //this is a dependency. 
    //Ideally I would inject it ( a map already created), but if I do it, I will loose connect !
    let map; 

    const connect = url => {
        map = new Map();
       console.log(`This url ${url} exists for illustration purposes only!`);
    };

    const get = key => {
        console.log(`You requested an object with key: ${key}`);
        return map.get(key);
    };


    const set = ( key, value ) => {
        ma.set(key, value);
        console.log(`You want to save value ${value} with key ${key}`);
    };

    return {
        connect,
        get,
        set
    };
};

module.exports.myCache =  myCache;

这是一个使用地图的简单缓存模块,用于演示目的。 在这个例子中,我有一个变量map,它在我调用connect 时被分配。

问题

这里的问题是我需要知道是否使用正确的参数调用了 map 中的方法 getset

因为 map 是在运行 connect 之后设置的,所以我无法监视它(例如使用 sinonjs)。一个可能的解决方案是已经内置到myCache 中的地图,但是API 会发生变化,这是我想要避免的。

问题

如何测试map 中的方法是否在不更改此模块 API 的情况下使用正确的参数调用?

【问题讨论】:

  • 如果无法注入已知依赖项,则依赖代码现在与该依赖项紧密耦合,这使得交换/模拟/存根以测试依赖代码变得相当困难隔离。如果最初的 API 设计不好,不更改 API 有什么意义?如果设计不好,现在就修复它,否则只有以后必须修复它才会更糟。
  • 你真的应该注入 map const myCache = map => {... 而不是通过手动创建它来紧密耦合。
  • 好的,假设我注入地图并松散连接。那么我怎么知道使用正确的参数正确创建了地图? (假设它有参数)
  • 谁在控制代码?不是你?我认为你需要研究依赖倒置和控制倒置。
  • 我在掌控之中。或许您可以举个例子说明您将如何解决它?

标签: javascript node.js unit-testing dependency-injection tdd


【解决方案1】:

您可以提供 Map 的 Mock 实现来跟踪和监视创建的 Map 对象。这将允许您在单元测试结束时检查创建了哪些映射以及在它们上调用了什么。

【讨论】:

    【解决方案2】:

    我看不到在注入依赖项时保持 API 不变的方法。

    您通常不会保持 API 不变。发生的情况是您扩展 API 以允许更精细的控制。

    const connect = url => {
        map = new Map();
       console.log(`This url ${url} exists for illustration purposes only!`);
    };
    

    为了让客户端控制地图,我们创建了一个接受地图作为参数的函数的新版本

    const connect_v2 = url, injected_map => {
        map = injected_map;
       console.log(`This url ${url} exists for illustration purposes only!`);
    };
    

    然后您可以通过让旧地图调用新地图来删除重复项,而无需更改其 API

    const connect = url => {
       connect_v2(url, new Map())
    };
    
    const connect_v2 = url, injected_map => {
       map = injected_map;
       console.log(`This url ${url} exists for illustration purposes only!`);
    };
    

    【讨论】:

      猜你喜欢
      • 2018-06-08
      • 2011-07-25
      • 2023-03-11
      • 1970-01-01
      • 2011-04-22
      • 1970-01-01
      • 2019-12-14
      • 1970-01-01
      • 2019-12-01
      相关资源
      最近更新 更多