Table of Contents

  1. 背景
  2. Jest
    1. API
    2. MOCK
  3. Nock

背景

在接触nodejs后,写完功能后,没有ut就会心里很虚。所以学习了下nodejs下UT框架–jest和http server mock–mock.

Jest

Jest 官方地址:Jest
Jest Docs:Jest docs
官网中介绍的用法已经挺详细了,平时的用法主要集中在这几个方面

API

  1. cases scope related

    • afterAll/afterEach/beforeAll/beforeEach(fn,timeout)
    • describe(name,fn)
      在describe block中也可以分别定义afterAll等,作用域为describe block
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      describe('upload task',()=>{
      beforeAll(() => {
      jest.resetModules();
      toolModule=require('../src/tool');
      toolModule.getResult=jest.fn(lib.getResult);
      });
      beforeEach(()=>{
      global.taskMap=new Map();
      global.pendingGetUrlResTask=[];
      });
      afterEach(()=>{
      global.pendingGetUrlResTask=undefined;
      global.pendingGetFileResTask=undefined;
      global.taskMap=undefined;

      });
      afterAll(()=>{
      nock.cleanAll();
      });
      it('multi process get task',async()=>{
      ...
      },30000);
      })
  2. data driven tests

    • describe.each(table)(name, fn, timeout)
      这个api的作用是将describe block作为一个test suit,实现只写一遍一类case测试多个data,这种case称为data driven tests.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      describe.each([[1,1,2],[1,2,3]])('test data add',(a,b,expected)=>{
      it(`returns ${expected}`, () => {
      expect(a + b).toBe(expected);
      });

      it(`returned value not be greater than ${expected}`, () => {
      expect(a + b).not.toBeGreaterThan(expected);
      });
      })
    • describe.only(name,fn),describe.only.each(table)(name, fn),describe.skip(name, fn),describe.skip.each(table)(name, fn)

  3. expect related

    • 简单数据结构等于/小于/大于
      expect(value)/.toBe(value)/.toBeLessThan(number | bigint)/.toBeLessThanOrEqual(number | bigint)

    • 复杂数据结构
      .arrayContaining(array)/.stringContaining(string)/.toEqual(value)/.toBeInstanceOf(Class)/.toContainEqual(item)/.toContain(item)/.toMatchObject(object)…

    • 异常
      .toThrow(error?)/.toThrowErrorMatchingSnapshot(hint?)/.toThrowErrorMatchingInlineSnapshot(inlineSnapshot)/

    • 自定义匹配器
      expect.extend(matchers)

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      expect.extend({
      toBeWithinRange(received, floor, ceiling) {
      const pass = received >= floor && received <= ceiling;
      if (pass) {
      return {
      message: () =>
      `expected ${received} not to be within range ${floor} - ${ceiling}`,
      pass: true,
      };
      } else {
      return {
      message: () =>
      `expected ${received} to be within range ${floor} - ${ceiling}`,
      pass: false,
      };
      }
      },
      });

      test('numeric ranges', () => {
      expect(100).toBeWithinRange(90, 110);
      expect(101).not.toBeWithinRange(0, 100);
      expect({apples: 6, bananas: 3}).toEqual({
      apples: expect.toBeWithinRange(1, 10),
      bananas: expect.not.toBeWithinRange(11, 20),
      });
      });
    • 正则匹配
      .toMatch(regexp | string)

  4. other

    • test/it.todo(name)
      当你在编写测试计划。这些测试将在最后的摘要输出中突出显示,因此您知道仍然需要执行多少测试。
    • test.concurrent…
      还处在实验阶段,没研究…

      MOCK

  • mock function

    经常会遇到的问题是:测试某个module的function,这个function用了其他导入模块的function,这个时候就需要mock依赖模块的function,使要测试的function自动调用我们mock好的,而不改变code.

    1
    2
    3
    4
    5
    jest.resetModules(); //卸载已经导入的module
    const depencyModule = require('./DepencyModule');//导入mock function所在的module(即测试module依赖的module)
    depencyModule.mockFunction = jest.fn().mockReturnValue()/jest.fn(myMockFunction) //将decpency module中的依赖的function换成mock
    const myModule = require('./MyModule');//导入测试module
    //之后在myModule中使用的depency module的function 就是已经mock好的
  • mock moudule
    第二种方法是mock整个module,调用module的class/function也变成相应的mock function。比如有很多模块都需要一个fs模块去读取文件,ut中不希望真正引入fs发生实际的文件操作。那就可以把整个fs mock掉。

    1
    jest.mock('fs');

其他mock的用法参考文档即可

Nock

Github: Nock
github上用法介绍的比较详细。the following is my sample code

1
2
3
4
5
6
7
8
9
const scope = nock('http://127.0.0.1:8181')
.defaultReplyHeaders({
'Content-Type':'application/octet-stream',
'X-DDC-Sample-SHA1':'a94a8fe5ccb19ba61c4c0873d391e987982fbbd3'
})
.get(`/v0/sample/file/taskId/${query}`)
.reply(200,()=>{
return fs.createReadStream(path.dirname(__filename)+'/file-sample');
});