2021-11-09 单元测试之sinon的入门

测试辅助工具 Sinon

Sinon 是用来辅助我们进行前端测试的,在我们的代码需要与其他系统或者函数对接时,它可以模拟这些场景,从而使我们测试的时候不再依赖这些场景。
Sinon 有主要有三个方法辅助我们进行测试:spystubmock

Sinon 的安装

在讲解用法前,先看一下我们的测试项目结构:

image.png

然后这里的测试例子用的是官网上的例子,once.js 的内容是:

export default function once(fn) {
  var returnValue,
    called = false;
  return function () {
    if (!called) {
      called = true;
      returnValue = fn.apply(this, arguments);
    }
    return returnValue;
  };
}

once.test.js 的内容为空。

那么接着安装 Sinon

npm install --save-dev sinon

Sinon 之 spy

官方对 spy 的解释:A test spy is a function that records arguments, return value, the value of this and exception thrown (if any) for all its calls. There are two types of spies: Some are anonymous functions, while others wrap methods that already exist in the system under test.

spy 生成一个间谍函数,它会记录下函数调用的参数,返回值,this 的值,以及抛出的异常。
spy 一般有两种玩法,一种是生成一个新的匿名间谍函数,另外一种是对原有的函数进行封装并进行监听。

搭好上面的结构后,直接在 once.test.js 里面写入 spy 的使用例子:

import { assert } from "chai";
import sinon from "sinon";
import once from "../src/once";

describe("测试Once函数", function () {
  it("传入Once的函数会被调用", function () {
    var callback = sinon.spy();
    var proxy = once(callback);

    proxy();

    assert(callback.called);
  });
});

如上面代码所示,sinon.spy() 会产生一个函数对象,当 once 调用这个函数对象后,这个函数对象通过 called 可以返回一个 bool 值,表示函数是否被调用。

测试结果为:

image.png

现在来看看 spy 的另一种玩法,即对原有函数的监控玩法,在 once.test.js 中加入以下测试用例:

it("对原有函数的spy封装,可以监听原有函数的调用情况", function () {
  const obj = {
    func: () => {
      return 1 + 1;
    },
  };
  sinon.spy(obj, "func");

  obj.func(3);

  assert(obj.func.calledOnce);
  assert.equal(obj.func.getCall(0).args[0], 3);
});

测试结果:

image.png

更多 spy 的 API 请参考

Sinon 之 Stub

来看看 Stub 的官方介绍:Test stubs are functions (spies) with pre-programmed behavior.
They support the full test spy API in addition to methods which can be used to alter the stub’s behavior.
As spies, stubs can be either anonymous, or wrap existing functions. When wrapping an existing function with a stub, the original function is not called.

stub 是带有预编程行为的函数。
简单点说,就是 spy 的加强版,不仅完全支持 spy 的各种操作,还能操作函数的行为。
spy 一样,stub 也能匿名,也能去封住并监听已有函数。
然而有一点和 spy 不同,当封装了一个已有函数后,原函数不会再被调用。

对于匿名的玩法我们就不说了,直接来封装的玩法,以下是对之前 spy 封装的修改:

it("对原有函数的stub封装,可以监听原有函数的调用情况,以及模拟返回", function () {
  const obj = {
    func: () => {
      console.info(1);
    },
  };
  sinon.stub(obj, "func").returns(42);

  const result = obj.func(3);

  assert(obj.func.calledOnce);
  assert.equal(obj.func.getCall(0).args[0], 3);
  assert.equal(result, 43);
});

测试结果如下:

image.png

根据测试结果可以了解到,原函数 func 的内容确实没有被执行,因为没有打印 1。

更多 API 查看 Sinon 之 stub

Sinon 之 mock

看一下官网的介绍:Mocks (and mock expectations) are fake methods (like spies) with pre-programmed behavior (like stubs) as well as pre-programmed expectations.
A mock will fail your test if it is not used as expected.

大致意思就是 mockspystub 一样的伪装方法,如果 mock 没有得到期望的结果就会测试失败。

这里的话可能讲述不是很清楚,那么看一下代码就很好理解了:

it("mock的测试", function () {
  var myAPI = {
    method: function () {
      console.info("运行method");
    },
    func: function () {
      console.info("运行method");
    },
  };

  var mock = sinon.mock(myAPI);
  mock.expects("method").once().returns(2);
  mock.expects("func").twice();

  myAPI.method();
  myAPI.func();
  myAPI.func();

  mock.verify();
});

在以上代码中,mock 其实和 stub 很像,只不过是 stub 是对对象中单个函数的监听和拦截,而 mock 是对多个。
mock 首先会对函数进行一个预期:

var mock = sinon.mock(myAPI);
mock.expects("method").once().returns(2);
mock.expects("func").twice();

比如 once 就是预期运行一次,如果最终验证时函数没有被执行或者执行多次都会抛出错误。
也可以操作返回结果,比如像 stub 一样 returns(2) 依然有效。
而且与 stub 一样,在 mock 监听后,原有函数内容将不会执行。

在进行了预期操作后,就对函数进行实际操作:

myAPI.method();
myAPI.func();
myAPI.func();

最后再进行验证操作

mock.verify();

运行上述测试用例得到以下结果

image.png

小结

Sinon 主要是一个测试辅助工具,通过伪装和拦截,来模拟与其他系统或函数的操作,可以解耦测试的依赖。
在上面只讲到了 Sinon 的 spystubmock 三个函数,其实还有 fake XHR(模拟 xhr 请求)、fack server(模拟服务器)以及 fake timer(模拟定时器)等操作。

作者:韩子卢
出处:https://www.cnblogs.com/vvjiang/

你可能感兴趣的:(2021-11-09 单元测试之sinon的入门)