资讯专栏INFORMATION COLUMN

Ajax单元测试傻瓜教程

30e8336b8229 / 1763人阅读

摘要:原文出处单元测试傻瓜教程请求经常容易发生错误,客户端发送的数据出问题,服务器端返回的数据有误都会导致请求错误。设置在我们开始单元测试之前,我们需要安装几个必须的工具。我们将用它来向你们展示如何对进行单元测试。

原文出处 :AJAX单元测试傻瓜教程

Ajax 请求经常容易发生错误,客户端发送的数据出问题,服务器端返回的数据有误都会导致 Ajax 请求错误。你不能保证与服务器的连接总是工作正常。Ajax请求需要将用户的输入发送给服务器并返回服务器响应,因此,对于数据的正确处理至关重要。
但是由于Ajax是异步的,测试它的同时必须保证独立性,我们如何才能在Ajax与服务器进行通信的时候对其进行单元测试呢?
不要怕,让我们看一看接下来的例子,学习一下如何对Ajax请求进行单元测试。

设置

在我们开始单元测试之前,我们需要安装几个必须的工具。

新建一个目录,用来存放必要的文件

使用 npm install mocha chai sinon 安装 Mocha, Chai, Sinon

测试运行器

为了使事情简单,我们将直接在浏览器中运行测试。如果你更喜欢基于命令行的测试的话,测试运行的结果也将会和浏览器中的结果完全一致。
我们将会使用以下的文件作为测试运行器。我将其命名为test.html



    
        Mocha Tests
        
    
    
        

注意mocha.js,mocha.css,sinon-1.17.1.js,chai.js的文件路径。因为我是用npm安装它们的,所以它们都在node_modules目录下。对于 Sinon,你可能需要更改文件名来匹配安装的版本,我在这里使用的是版本是1.17.1。同时也注意testApi.js,test.js这两个文件,这两个文件作为我的实例模块和测试用例,我将会在接下来逐一介绍它们。

实例模块

接下来,我们将创建一个基础的模块,该模块将会发送一些Ajax请求。我们将用它来向你们展示如何对Ajax进行单元测试。
我们将该文件命名为testApi.js

var testApi = {
    get: function(callback) {
        var xhr = new XMLHttpRequest();
        xhr.open("GET", "http://jsonplaceholder.typicode.com/posts/1", true);

        xhr.onreadystatechange = function() {
            if(xhr.readyState == 4) {
                if(xhr.status == 200) {
                    callback(null, JSON.parse(xhr.responseText));
                }
                else {
                    callback(xhr.status);
                }
            }
        };

        xhr.send();
    },

    post: function(data, callback) {
        var xhr = new XMLHttpRequest();
        xhr.open("POST", "http://jsonplaceholder.typicode.com/posts", true);

        xhr.onreadystatechange = function() {
            if(xhr.readyState == 4) {
                callback();
            }
        };

        xhr.send(JSON.stringify(data));
    }
};

这段代码开起来应该很熟悉,我们写了两个函数,一个函数中使用GET方法获取数据,另一个函数中使用POST方法向服务器发送数据,这些都是最普通的 Ajax请求。我们在这里使用了JSONPlaceholder API,它是一个免费的在线REST服务,你可以使用它提供的模拟数据,非常适合快速测试。

测试用例框架

之后我们需要创建一个框架,在里面添加每个情景的测试集。该文件被命名为test.js

chai.should();

describe("TestAPI", function() {
  //Tests etc. go here
});

Mocha中使用describe来创建一个测试用例,该测试用例便是我们添加测试代码的地方。
chai.should()将允许我们使用 "should style" 断言。这意味着我们可以轻松的验证我们的测试结果,如:someValue.should.equal(12345)

测试GET请求

我们的示例模块中有一个get函数,该函数可以被用来加载服务器传送过来的数据。我们将会创建一个测试函数来证明由服务器取到数据是一个JSON数据。但是该GET请求是由XMLHttpRequest发出的,由于我们测试的时候并没有服务器接收我们的数据,所以我们不能真的发出一个 Http 请求,那么我们如何才能避免真的发出请求呢?又如何能得到返回的数据呢?
别着急,这个时候就到了 Sinon 出场了。我们一开始在就在test.html中引用了 Sinon 的库,有了 Sinon,我们就可以模拟服务器响应。我们可以将XMLHttpRequest用一个替身来代替,我们称之为 fake XMLHttpRequest,这样我们就能在测试中轻松控制Ajax请求了。
我们需要稍微更新一下我们的测试用例框架,以下是更改之后的test.js文件。

chai.should();

describe("TestAPI", function() {
    beforeEach(function() {
        this.xhr = sinon.useFakeXMLHttpRequest();

        this.requests = [];
        this.xhr.onCreate = function(xhr) {
            this.requests.push(xhr);
        }.bind(this);
    });

    afterEach(function() {
        this.xhr.restore();
    });


    //Tests etc. go here
});

beforeEachafterEach就像他们的名字一样,将会在每一次的测试前和测试后被调用。在每一个测试之前,我们实例化了一个 fake XMLHttpRequest 并且将每一个被创建的 fake request 放入了一个数组中,这些值被存储在this.xhrthis.request中,这样我们就可以在该测试中的其他函数中使用了。

在每一次测试之后,我们使用了this.xhr.restore来恢复初始的XMLHttpRequest对象。

现在,我们可以开始在test.js中写下我们的第一个测试集:

it("should parse fetched data as JSON", function(done) {
    var data = { foo: "bar" };
    var dataJson = JSON.stringify(data);

    testApi.get(function(err, result) {
        result.should.deep.equal(data);
        done();
    });

    this.requests[0].respond(200, { "Content-Type": "text/json" }, dataJson);
});

我们定义了一个对象data和它的JSON版本dataJson作为我们将要传递的数据。下一步,我们调用了testApi.call,在它的回掉函数中我们使用了result.should.deep.equal来验证结果是不是与我们所期望的数据一致。我们还调用了done(),它的作用是告诉 Mocha 该异步测试完成了。在这里,要注意done是测试函数中的一个参数。
最后,我们调用了this.requests[0].respond。你还记得之前的beforeEach函数么?它在每一次的测试开始之前,将所有的 fake XMLHttpRquest 放入了this.requests中。当我们的测试调用testApi.get时,它创建了一个请求。这个请求被存入了this.requests这个数组中,this.requests[0]就代表了这个请求。
通常来说,XMLHttpRequest 没有respond函数,这里的respond用来响应一个 fake request。我们在该响应中设置状态码为200,意思是成功响应。同时,我们将响应头中的Content-Type设置为text/json,这是因为我们传递的是 JSON 数据。respond函数中的最后一个参数表示响应体,我们将其设置为之前创建好的dataJson变量。
fake XMLHttpRequest 模拟了一个 GET 请求的响应,在得到响应之后,testApi.get中的回掉函数将会被调用。该回调函数中,我们将响应中得到的结果与data变量做对比:

testApi.get(function(err, result) {
    result.should.deep.equal(data);
    done();
});

因为之前我们创建了datadataJson变量来代表传递的数据,所以如果响应正确,响应的数据应该被解析成一个对象。
现在,我们可以在浏览器中运行我们的测试了,打开test.html文件,你应该可以看到关于测试通过的信息。

测试POST请求

在我们的示例中还有一个向服务器发送数据的post函数,发送的数据是 JSON 格式的。接下来我们就要完成对该函数的测试。

it("should send given data as JSON body", function() {
    var data = { hello: "world" };
    var dataJson = JSON.stringify(data);

    testApi.post(data, function() { });

    this.requests[0].requestBody.should.equal(dataJson);
});

就和之前一样,我们首先定义了一个测试数据data和它的 JSON 格式的变量dataJson。之后我们调用了testApi.post。与之前测试 GET 请求不一样的地方是,这一次我们只需要验证要被发送的数据是否被正确的转换成了 JSON 格式,因为我们只需要保证 POST 请求中发出的数据是正确的,因此我们的回掉函数是空的。
该段代码中最后一行使用了一个断言来确定发送数据的正确性。与之前一样,我们使用了 fake XMLHttpRequest,但是这一次我们要证明它携带了正确的数据。POST 请求中携带的数据存放在 fake XMLHttpRequest 的 requestBody属性中,我们将其与dataJson作比较来验证我们的行为。

错误测试

作为最后一个示例,让我们来是测试一个失败的请求。因为网络连接中可能出现很多问题,同时服务器也可能出现问题,并且我们不应该让我们网站的用户对具体的错误信息感到疑惑,所以错误测试非常重要。
示例模块中的回调函数中有两个参数,第一个参数就是错误信息,第二个参数则是每一次 Http 请求响应得到的结果。代码如下:

it("should return error into callback", function(done) {
    testApi.get(function(err, result) {
        err.should.exist;
        done();
    });

    this.requests[0].respond(500);
});

由于是错误测试,所以这一次我们不需要任何数据。我们调用了testApi.get,并在其回掉函数中来验证 error 参数的存在。为了模拟响应错误,最后一行中的 fake XMLHttpRequest 发送了一个内部服务器错误的状态码 500 来触发错误处理程序。

总结

Ajax请求的测试是很重要的,如果你能证明每一次请求都是正确的,那么你应用程序中的其他部分就能完全相信每一次 Ajax 请求得到的数据。
假如你正在使用 JQuery Ajax,测试的方法与例子的方法是一模一样的。你同样可以使用 Sinon 中的 fake XMLHttpRequests。
当然,Sinon 中并不只有 fake XMLHttpRequest, 它还有 fake Server 用来模拟服务器响应,感兴趣的话可以去 Sinon 的官网了解。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/86217.html

相关文章

  • 前端资源系列(4)-前端学习资源分享&前端面试资源汇总

    摘要:特意对前端学习资源做一个汇总,方便自己学习查阅参考,和好友们共同进步。 特意对前端学习资源做一个汇总,方便自己学习查阅参考,和好友们共同进步。 本以为自己收藏的站点多,可以很快搞定,没想到一入汇总深似海。还有很多不足&遗漏的地方,欢迎补充。有错误的地方,还请斧正... 托管: welcome to git,欢迎交流,感谢star 有好友反应和斧正,会及时更新,平时业务工作时也会不定期更...

    princekin 评论0 收藏0
  • linux宝塔面板安装傻瓜教程:宝塔Linux面板7.6.0安装教程

    摘要:一键配置宝塔面板怎么安装到数据盘教程二个命令宝塔面板怎么安装到数据盘教程二个命令今天,刚买了一台香港云服务器,系统盘是,数据盘是,安装宝塔面板之后发现磁盘的容量不对Linux宝塔面板安装傻瓜教程:宝塔Linux面板7.6.0安装教程1.介绍宝塔Linux面板7.4.5版本是基于Centos开发的,为了最好的兼容性,请优先考虑使用Centos8.x系统系统兼容性顺序:Centos8.x > C...

    番茄西红柿 评论0 收藏2637
  • PHPRAP v1.0.3 发布,修复BUG和新增部分功能

    摘要:,是一个轻量级开源接口文档管理系统,致力于减少前后端沟通成本,提高团队协作开发效率,打造版的。官方网站演示网站作者博客官方群 PHPRAP,是一个PHP轻量级开源API接口文档管理系统,致力于减少前后端沟通成本,提高团队协作开发效率,打造PHP版的RAP。 更新记录 【修复】修复安装步骤第一步conpile目录权限检测错误的BUG 【修复】修复mock规则类型不存在时报错的BUG 【...

    Apollo 评论0 收藏0
  • PHPRAP v1.0.3 发布,修复BUG和新增部分功能

    摘要:,是一个轻量级开源接口文档管理系统,致力于减少前后端沟通成本,提高团队协作开发效率,打造版的。官方网站演示网站作者博客官方群 PHPRAP,是一个PHP轻量级开源API接口文档管理系统,致力于减少前后端沟通成本,提高团队协作开发效率,打造PHP版的RAP。 更新记录 【修复】修复安装步骤第一步conpile目录权限检测错误的BUG 【修复】修复mock规则类型不存在时报错的BUG 【...

    idealcn 评论0 收藏0
  • PHPRAP v1.0.3 发布,修复BUG和新增部分功能

    摘要:,是一个轻量级开源接口文档管理系统,致力于减少前后端沟通成本,提高团队协作开发效率,打造版的。官方网站演示网站作者博客官方群 PHPRAP,是一个PHP轻量级开源API接口文档管理系统,致力于减少前后端沟通成本,提高团队协作开发效率,打造PHP版的RAP。 更新记录 【修复】修复安装步骤第一步conpile目录权限检测错误的BUG 【修复】修复mock规则类型不存在时报错的BUG 【...

    jayzou 评论0 收藏0

发表评论

0条评论

30e8336b8229

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<