简体   繁体   English

Node.js单元测试

[英]Nodejs Unit Testing Urls

What is the best way to do this incrementally? 增量执行此操作的最佳方法是什么? Eg. 例如。 Some urls must be accessed before others to populate a DB etc. Is there an idiomatic node way of unit testing? 必须先访问某些URL才能填充数据库等。某些单元测试是否有惯用的节点方法?

I currently read unit test data in from a json file, then request based on that. 我目前从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();
}

To add to Peter Lynos' advise, allow me to introduce to you the correct idea of Unit Testing. 要补充Peter Lynos的建议,请允许我向您介绍单元测试的正确概念。 When performing unit testing, a lot of people ask the wrong question. 执行单元测试时,很多人会问错问题。 It's not "How do I test this", but "What do I test for". 不是“我如何测试”,而是“我要测试什么”。 In your case, you want to test your code, logic, and nothing else. 就您而言,您想测试您的代码,逻辑,而不要测试其他任何东西。 This means you have to remove all external factors, which includes 3rd party libraries, npm modules, and even node.js core API modules. 这意味着您必须删除所有外部因素,包括第三方库,npm模块,甚至是node.js核心API模块。

Ask yourself this - can you copy your test suite and run it without having to do hours of setting up the environment? 问问自己-您是否可以复制测试套件并运行它而无需花费数小时来设置环境? You should be able to. 你应该能够。 That's the whole point of writing unit tests - making it run in isolation to ensure that your code is correct. 这就是编写单元测试的全部要点-使其独立运行以确保您的代码正确。 We call that "environment" where your code can run in isolation a "control environment", similar to the same term used in scientific circles. 我们称您的代码可以独立运行的“环境”为“控制环境”,类似于科学界使用的相同术语。

Now to achieve this, you need to understand the concept of fixtures and mocks. 现在要实现这一点,您需要了解固定装置和模拟装置的概念。 Fixtures are there to create your control environment. 可以使用夹具来创建您的控制环境。 It does so by creating a bunch of mock objects, where each mock object takes an input and produces an output. 它是通过创建一堆模拟对象来实现的,每个模拟对象都接受一个输入并产生一个输出。 This way, you have exact control over all aspects of your code, and it makes it dead simple to test all kinds of stuff from DB operations to REST requests. 这样,您就可以完全控制代码的各个方面,这使得测试从DB操作到REST请求的所有内容变得非常简单。

Finally, having understood that: 最后,了解到:

  1. The best test suite is one that can run in an isolated, control environment 最好的测试套件是可以在隔离的控制环境中运行的套件
  2. Fixtures are used to create that environment by providing your code with mock objects 夹具用于通过为代码提供模拟对象来创建该环境
  3. Mock objects take in an input and returns an output 模拟对象接受输入并返回输出
  4. The 3 things above can only be achieved if you had coded your project with 100% injected dependency 仅当您使用100%注入依赖项对项目进行编码时,才能实现上述三件事

Mock Objects 模拟对象

Assuming that in your function foo() you want to read a file's contents, here's how your mock should look like: 假设您要在函数foo()中读取文件的内容,则模拟结果如下所示:

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

And then in your test code, you try to read the file 'unit-test-1', and it will return 'This is the file contents'. 然后在测试代码中,尝试读取文件“ unit-test-1”,它将返回“ This is the file contents”。

Dependency Injection 依赖注入

All the above would be extremely difficult if your project is not written to have their dependencies injected externally. 如果您的项目未编写为从外部注入其依赖项,则上述所有内容将非常困难。 Right now my convention is that all modules must have a make() function which takes an object that contains all its dependencies. 现在,我的约定是所有模块都必须具有make()函数,该函数接受包含其所有依赖项的对象。 Here's a simple example: 这是一个简单的例子:

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

Then you need either a factory or a DI container to build that object for your, automatically constructing its dependencies. 然后,您需要一个工厂或一个DI容器来为您构建该对象,并自动构建其依赖关系。

Only then would BDD and TDD be fun in your project. 只有这样,BDD和TDD才能在您的项目中变得有趣。 Hope this helps! 希望这可以帮助!

OK, a few tips. 好的,一些技巧。 Your code doesn't seem to be using any test framework whatsoever, so look at at least using commonJS asserts or a testing framework. 您的代码似乎根本没有使用任何测试框架,因此请至少查看使用commonJS断言或测试框架。 I prefer jasmine , but there are several good ones. 我更喜欢茉莉花 ,但是有几个很好的。 Jasmine has great support for spies and asynchronous tests. Jasmine对间谍程序和异步测试提供了强大的支持。 As a side comment, these are not unit tests, which by definition wouldn't hit a database, these are most likely application/system tests. 附带说明一下,这些不是单元测试,从定义上讲不会打入数据库,它们很可能是应用程序/系统测试。 You might want to consider writing some pure unit tests for your server side code in addition to these system level tests that send live data through your whole stack. 除了这些通过整个堆栈发送实时数据的系统级测试之外,您可能还想考虑为服务器端代码编写一些纯单元测试。

On the topic of test prerequisites, generally try to make each test as independent as possible. 关于测试先决条件的主题,通常尝试使每个测试尽可能独立。 But when total independence is not avoidable, most unit testing frameworks have a concept of a setup / teardown pair of functions that are called before and after each test. 但是,当无法避免完全独立时,大多数单元测试框架都有一个“ setup / teardown ”功能对的概念,这些功能在每次测试之前和之后都被调用。 In jasmine , this is the beforeEach function. jasmine中 ,这是beforeEach函数。 Pre-loading DB objects as "fixtures" is sometimes done in the Rails community. 有时在Rails社区中将数据库对象预加载为“夹具”。 There is also the notion of "factories". 还有“工厂”的概念。 Each strategy has strengths and shortcomings. 每种策略都有优点和缺点。 I'm not sure if there are node libraries for either factories or fixtures, but do a web search. 我不确定是否有用于工厂或固定装置的节点库,但可以进行网络搜索。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM