资讯专栏INFORMATION COLUMN

[gist]用 jest 轻松测试 JavaScript

CoderStudy / 3205人阅读

摘要:的测试不管在用还是都是很头疼的事情但是自从有了一口气写个测试腰也不疼了头也不疼了只需要个理由在说用测为什么好之前我们先来看我们要测的一个例子栗子比如我要写一个模块要去取用户的和他所有的数量那么我们应该有一个的我们还需要一个的大同小异略去最后

from oyanglul.us

Javascript 的测试, 不管在用 jasmine 还是 mocha,
都是很头疼的事情. 但是自从有了 jest, 一口气写7个测试, 腰也不疼了, 头也不疼了.

只需要 3 个理由

在说用 jest 测为什么好之前,我们先来看我们要测的一个例子.

栗子

比如我要写一个模块要去取github 用户的follower 和他所有 repo 的 follower 数量.

那么我们应该有一个 User 的 Model.

// user.js
var $ = require("jquery");
function User(name) {
  this.name = name;
  this.followers = 0;
}
User.prototype.fetch = function(){
  return $.ajax({
    url: "https://api.github.com/users/" + this.name,
    method: "get",
    dataType: "json"
  }).then(function(data){
      this.followers = data.followers;
  }.bind(this));
};
module.exports = User;

我们还需要一个 repo 的 model, 大同小异略去

最后, 整合这俩我要的东西, 并显示在页面上

// follower.js
var $ = require("jquery");
function followerOf(user, repo) {
  user.fetch().then(repo.fetch).then(function(_){
    $("#content").text(user.name +""s followers: " + user.followers +
                       " and his repo "+ repo.name +""s followers:" + repo.followers);
    });
};

module.exports = followerOf;

--

1. Auto Mock

自动 mock 实在是最大的亮点, jest 重写了 require, 所以你的代码里的所有 require 来的东西都自动 mock.

因为在你的测试中往往只关心一个模块, 对于他的所有依赖其实都是无所谓的.

在例子中, 如果我们在测 repo.js 的时候完全不关心那两个 jquery 的 ajax 方法到底
写对没写对,反正我们期望能从 ajax 里面拿到我们想要的东西就对了. 因此, 我希望 jquery 的
所有方法都是 mock 的. jest 让你很轻松的做到这点, 因为是自动mock所有require 的东西, 而
对于目标测试模块, 只需要说我dontMock 我的目标模块就好了.

jest.dontMock("../repo");
describe("Repo Model", function(){
  var repo;
  beforeEach(function(){
        var $ = require("jquery").setAjaxReturn({stargazers_count: 23});
        var Repo = require("../repo");
    repo = new Repo("jcouyang", "gira");

    });

  it("should populate properties with data from github api", function(){
        repo.fetch();
        expect(repo.followers).toBe(23);
  });
});

所以这个测试看起来就跟文档一样了,

dontMock("./repo") 说明我关心repo
这个模块, 其他我都不 care.

before 是我要进行操作所需要的东西.

我要 jquery ajax 请求给我想要的数据

我要一个我要测的 Repo 类的实例

it 说明我关心地行为是神马

我关心 fetch 的行为,是去取数据并给我把数据填充到我的 repo 实例中

  

你可能要问 segAjaxReturn 是哪里冒出来的. 忍一忍稍后告诉你.

有没有看虽然我显式的 mock jquery, 但是 Repo 里面 require 的 jquery 其实是假的, 不然我们就真的访问
github api 了. 那样就不会每次都返回 23 个 follower 了.

2. jsdom

好了现在我们来测 follower.js, 先看 follower 到底干了什么, 拿到 user 和 repo
的信息然后组成一句话放到页面 id 为 content 的元素下面.

好, 所以我们关心
- 组出来的话对不对
- 有没有放到 content 元素下, 所以 jquery 的操作对不对也是我们关心的一部分

我们不关心
- user 干了什么
- repo 干了什么

这样,关心的就是不能 mock 的

jest.dontMock("../follower")
    .dontMock("jquery");
describe("follower", function(){
  var user, repo, follower;
    var $ = require("jquery");
  beforeEach(function(){
        var Repo = require("../repo");
        var User = require("../user");
        follower = require("../follower");
        user = new User("jcouyang");
    repo = new Repo("jcouyang", "gira");
    // 我们不关心 user, 但是我们希望他能返回一个 deferred 类型
      user.fetch.mockReturnValue($.Deferred().resolve("dont care"));
    // 我们让我们不关心的 user 和 repo 返回我们期望的东西就好
        user.name ="jcouyang";
        user.followers = 20;
        repo.name = "gira";
        repo.followers = 21;
    // 期待页面上有一个  id 为 content 的元素
        document.body.innerHTML = "

"; }); it("should populate properties with data from github api", function(){ follower(user,repo); // 希望 content 上能得到想要的内容 expect($("#content").text()).toBe("jcouyang"s followers: 20 and his repo gira"s followers:21"); }); });
3. Manual Mock

好了, 说好的解释 setAjaxReturn是怎么回事的

嗯嗯, 是这样的, 虽然 jest 自动 mock 了我们不关心的模块, 但是我们还是会希望
这个 mock 的玩意能有一些我们期望的行为, 也就是按我们的期望返回一些东西. 比如
这里就是我们不关心 ajax 的逻辑, 但是我们需要他能给我们返回一个东西,并且可以
thenable. 所以单纯的 mock 对象或函数都不能做到, 所以有了 manual mock 这种东西.

用 manual mock 需要建一个__ mocks__ 文件夹,然后把所有的 mock 都扔进去. 比如
我想 mock jquery, 那么我建一个jquery.js 扔进去

var data = {};
var mockDefered = function(data){
    return {
        then: function(cb){
            return mockDefered(cb(data));
        }
    };
};

function ajax() {
  return mockDefered(data);
}

function setAjaxReturn(shouldbe){
    data = shouldbe;
}
exports.setAjaxReturn = setAjaxReturn;
exports.ajax = ajax;

终于看见setAjaxReturn在哪里定义了:sweat_smile: 这里暴露两个函数
- setAjaxReturn: 可以设置我希望 ajax 返回的值
- ajax: 单纯的返回这个 thenable.

所以我也不需要显示的声明 mock jquery什么什么的, 直接在测试里设置ajax 的返回值就好了.

var $ = require("jquery").setAjaxReturn({stargazers_count: 23});

这是 repo 里面 require 的 jquery 已经被 mock 并且只要掉 ajax 都会返回我
期望的值.

etc

并行测试:
还用说么, 既然已经如此模块化好了, user repo 以及 follower 的测试完全是互不依赖.
没有什么理由一个一个测. 因此3个测试的耗时取决于最长时间的那个. 所以如果有
那个测试特别耗时,说明模块还不够细, 多拆几个就快了.

promise: 使用 pit() 来测试 thenable 的对象, 比如 repo 的例子,就 keyi
写成

pit("should populate properties with data from github api", function(){
  return repo.fetch().then(
    expect(repo.followers).toBe(23);
  );
});

Timer mocks: 可以使用 mock 的 timer 和 ticks, 也就是你可以加速
所有的setTimeout, setInterval, clearTimeout, clearInterval行为. 不需要等待.

setTimeout(function() { callback(); }, 1000);
 expect(callback).not.toBeCalled();
 jest.runAllTimers();
expect(callback).toBeCalled()
Wrapup

所以说白了, jest 其实也是个概念, 推荐使用模块化的思想, 这样我只需要保证每个接口的 IO 正确, 就可以保证整个程序没问题. 这样划分下来测试就会变得简单到只需要关心当然模块的 IO 从而
可以 mock 掉所有其他依赖. 真正模块化好的代码单纯的只用 jasmine 或者 mocha
都应该是很好测的. 只是在这个概念之上省去了很多不必要的 mock 代码, 因为要 mock 的
依赖总是占大多数的, 而关心的, 往往只是那么一两个.

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

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

相关文章

  • JS/React 开发者的 Atom 终极配置

    摘要:开发者的终极配置原文作者原文链接根据多年以来不断完善配置的经验,决定这次给也来一个大改造。快捷键帮助开发人员在不同的编辑器之间保持一致的编码风格。一组专注,用于优化现代开发生产力的命令集,目标是符合推荐的代码规范。 JS/React 开发者的 Atom 终极配置 原文作者:Elad Ossadon 原文链接:The Ultimate Atom Editor Setup (+for J...

    LiangJ 评论0 收藏0
  • 【全栈React】第23天: 实现测试

    摘要:包包含由团队提供的测试实用程序。将在一个名为的目录中自动查找整个树中的测试文件是的带有下划线。让我们为时间轴组件创建第一个测试。其中之一是命令。现在我们已经编写了第一个测试并确认了我们的设置我们将在明天开始测试我们的时间轴组件。 本文转载自:众成翻译译者:iOSDevLog链接:http://www.zcfy.cc/article/3807原文:https://www.fullstac...

    airborne007 评论0 收藏0
  • (译 & 转载) 2016 JavaScript 后起之秀

    摘要:在年成为最大赢家,赢得了实现的风暴之战。和他的竞争者位列第二没有前端开发者可以忽视和它的生态系统。他的杀手级特性是探测功能,通过检查任何用户的功能,以直观的方式让开发人员检查所有端点。 2016 JavaScript 后起之秀 本文转载自:众成翻译译者:zxhycxq链接:http://www.zcfy.cc/article/2410原文:https://risingstars2016...

    darry 评论0 收藏0
  • Mocha 和 Chai 入门初探

    摘要:转载自楼主个人博客和入门初探在和作比较的时候两者主要的不同就是的集成度比较高内置断言库而需要搭配额外的断言库在此选择了比较流行的作为断言库风格的选择其中又有好几种断言风格我们经常见到的其实就是风格的其中我较喜欢因为它可以直接以属性的方式嵌入 转载自楼主个人博客 Mocha 和 Chai 入门初探 Chai 在和 jest 作比较的时候, 两者主要的不同就是 jest 的集成度比较高内置...

    caoym 评论0 收藏0
  • 使Jest测试JavaScript(Mock篇)

    摘要:测试调用断言的执行后返回断言被调用断言被调用了一次断言传入的参数为所创建的函数还可以设置返回值,定义内部实现或返回对象。 在本篇教程中,我们会介绍 Jest 中的三个与 Mock 函数相关的API,分别是jest.fn()、jest.spyOn()、jest.mock()。使用它们创建Mock函数能够帮助我们更好的测试项目中一些逻辑较复杂的代码,例如测试函数的嵌套调用,回调函数的调用等...

    YorkChen 评论0 收藏0

发表评论

0条评论

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