Nodejs 单元测试 URL

发布于 2024-11-06 11:04:56 字数 652 浏览 1 评论 0原文

增量地执行此操作的最佳方法是什么? 例如。必须先访问某些网址,然后再访问其他网址才能填充数据库等。是否有惯用的单元测试节点方式?

我目前从 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();
}

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?

I currently read unit test data in from a json file, then request based on that.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

梦回梦里 2024-11-13 11:04:56

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

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

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

最后,了解以下内容:

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

仅当您使用 100% 注入依赖项模拟对象

假设您想要在函数 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');
    }
}

:在您的测试代码中,您尝试读取文件“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 才会在您的项目中变得有趣。希望这有帮助!

To add to Peter Lynos' advise, allow me to introduce to you the correct idea of Unit Testing. 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.

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.

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

Mock Objects

Assuming that in your function foo() you want to read a file's contents, here's how your mock should look like:

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'.

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. 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.

Only then would BDD and TDD be fun in your project. Hope this helps!

可爱咩 2024-11-13 11:04:56

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

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

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. I prefer jasmine, but there are several good ones. Jasmine has great support for spies and asynchronous tests. 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. In jasmine, this is the beforeEach function. Pre-loading DB objects as "fixtures" is sometimes done in the Rails community. 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文