Ajax单元测试傻瓜教程

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

Ajax 请求常常容易发生错误,客户端发送的数据出问题,服务器端返回的数据有误都会致使 Ajax 请求错误。你不能保证与服务器的链接老是工做正常。Ajax请求须要将用户的输入发送给服务器并返回服务器响应,所以,对于数据的正确处理相当重要。
可是因为Ajax是异步的,测试它的同时必须保证独立性,咱们如何才能在Ajax与服务器进行通讯的时候对其进行单元测试呢?
不要怕,让咱们看一看接下来的例子,学习一下如何对Ajax请求进行单元测试。html

设置

在咱们开始单元测试以前,咱们须要安装几个必须的工具。node

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

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

测试运行器

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

<!DOCTYPE html>
<html>
    <head>
        <title>Mocha Tests</title>
        <link rel="stylesheet" href="node_modules/mocha/mocha.css">
    </head>
    <body>
        <div id="mocha"></div>
        <script src="node_modules/mocha/mocha.js"></script>
        <script src="node_modules/sinon/pkg/sinon-1.12.2.js"></script>
        <script src="node_modules/chai/chai.js"></script>
        <script>mocha.setup('bdd')</script>
        <script src="testApi.js"></script>
        <script src="test.js"></script>
        <script>
            mocha.run();
        </script>
    </body>
</html>

注意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 的官网了解。

相关文章
相关标签/搜索