【问题标题】:Nodejs Unit Testing UrlsNodejs 单元测试网址
【发布时间】:2011-08-23 20:42:55
【问题描述】:

渐进式执行此操作的最佳方法是什么? 例如。必须先访问某些 url 才能填充数据库等。是否有惯用的节点方式进行单元测试?

我目前从一个 json 文件中读取单元测试数据,然后根据它进行请求。

function urlTestFn(test){
    var req = requestProperties(test);
    var request = http.request(req, function(resp) {
        resp.setEncoding('utf8');
        resp.on('data',function(data) {
            if(data == JSON.stringify(test.response)) {
                //success
            } else {
                sys.puts('fail');
            }
        });
    });
    if(req.method == 'POST'){
        request.write(JSON.stringify(test.postData));
    }
    request.end();
}

【问题讨论】:

    标签: unit-testing url testing node.js asynchronous


    【解决方案1】:

    为了补充 Peter Lynos 的建议,请允许我向您介绍单元测试的正确理念。在执行单元测试时,很多人会问错误的问题。这不是“我如何测试这个”,而是“我要测试什么”。在您的情况下,您想要测试您的代码、逻辑,而不是其他任何东西。这意味着您必须移除所有外部因素,包括 3rd 方库、npm 模块,甚至 node.js 核心 API 模块。

    问问自己这个问题 - 您能否复制您的测试套件并运行它而无需花费数小时设置环境?你应该能够。这就是编写单元测试的重点——让它独立运行以确保你的代码是正确的。我们将您的代码可以独立运行的“环境”称为“控制环境”,类似于科学界使用的同一术语。

    现在要实现这一点,您需要了解夹具和模拟的概念。固定装置可用于创建您的控制环境。它通过创建一堆模拟对象来做到这一点,其中每个模拟对象接受一个输入并产生一个输出。通过这种方式,您可以精确控制代码的各个方面,并且可以非常简单地测试从 DB 操作到 REST 请求的各种内容。

    终于明白了:

    1. 最好的测试套件是可以在隔离的控制环境中运行的套件
    2. Fixtures 用于通过为您的代码提供模拟对象来创建该环境
    3. 模拟对象接受输入并返回输出
    4. 只有在使用 100% 注入依赖项对项目进行编码时,才能实现上述 3 件事

    模拟对象

    假设你想在你的函数 foo() 中读取文件的内容,你的 mock 应该是这样的:

    var FsMock = {
        readFile : function readFile(path, encoding, callback) {
            if (path === 'unit-test-1')
                callback(null, 'This is the file contents');
            else
                callback(new Error('Unexpected error');
        }
    }
    

    然后在您的测试代码中,您尝试读取文件“unit-test-1”,它会返回“这是文件内容”。

    依赖注入

    如果您的项目没有编写为将其依赖项从外部注入,那么上述所有内容都将非常困难。现在我的约定是所有模块都必须有一个 make() 函数,该函数接受一个包含其所有依赖项的对象。这是一个简单的例子:

    var Fs = null;
    var Path = null;
    
    var TestObj = module.exports = {
        make : function make(args) {
            if ('undefined' === typeof args.fs)
                throw new Error('Dependency: FS module needed');
            if ('undefined' === typeof args.path)
                throw new Error('Dependency: Path module needed');
    
            Fs = args.fs;
            Path = args.fs;
    
            return Object.create(this);
        }
    }
    

    然后您需要一个工厂或一个 DI 容器来为您构建该对象,自动构建其依赖项。

    只有这样 BDD 和 TDD 才能在您的项目中变得有趣。希望这会有所帮助!

    【讨论】:

      【解决方案2】:

      好的,一些提示。您的代码似乎没有使用任何测试框架,所以至少看看使用 commonJS 断言或测试框架。我更喜欢jasmine,但也有几个不错的。 Jasmine 对间谍和异步测试有很好的支持。作为旁注,这些不是单元测试,根据定义不会命中数据库,这些很可能是应用程序/系统测试。除了通过整个堆栈发送实时数据的系统级测试之外,您可能还需要考虑为服务器端代码编写一些纯单元测试。

      关于测试先决条件,通常尽量使每个测试尽可能独立。但是当完全独立是不可避免的时候,大多数单元测试框架都有一个 setup/teardown 对在每次测试之前和之后调用的函数的概念。在jasmine 中,这是beforeEach 函数。有时在 Rails 社区中将 DB 对象作为“fixtures”预加载。还有“工厂”的概念。每种策略都有优点和缺点。我不确定是否有适用于工厂或固定装置的节点库,但请进行网络搜索。

      【讨论】:

        猜你喜欢
        • 2018-10-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多