Jest 断言归纳

Jest 实在是很方便,上手简单,几乎零配置。记录一下学习 Jest matchers。附上大部分说明及示例。

普通匹配器

  • toBe - toBe 使用 Object.is 来测试是否完全相等
  • .not - 用来测试相反的用例
  • .toEqual - 如果你想检查某个对象的值,请改用 toEqual。
  • 最简单的测试值的方法是看是否精确匹配。

    test('two plus two is four', () => { 
        expect(2 + 2).toBe(4); 
    

    toEqual

    如果你想检查某个对象的值,请改用 toEqual。

    test('object assignment', () => { 
        const data = {one: 1}; 
        data['two'] = 2; 
         expect(data).toEqual({one: 1, two: 2}); 
    

    用来测试相反的用例

    test('null', () => {
      const n = null;
      expect(n).not.toBeUndefined();
      expect(n).not.toBeTruthy();
    

    布尔值匹配器

  • toBeNull 只匹配 null
  • toBeUndefined 只匹配 undefined
  • toBeDefined 与 toBeUndefined 相反
  • toBeTruthy 匹配任何 if 语句为真
  • toBeFalsy 匹配任何 if 语句为假
  • test('null', () => {
      const n = null;
      expect(n).toBeNull();
      expect(n).toBeDefined();
      expect(n).not.toBeUndefined();
      expect(n).not.toBeTruthy();
      expect(n).toBeFalsy();
    test('zero', () => {
      const z = 0;
      expect(z).not.toBeNull();
      expect(z).toBeDefined();
      expect(z).not.toBeUndefined();
      expect(z).not.toBeTruthy();
      expect(z).toBeFalsy();
    

    数字匹配器

  • .toBeGreaterThan() - 大于
  • .toBeGreaterThanOrEqual() 大于等于
  • .toBeLessThan() - 小于
  • .toBeLessThanOrEqual() - 小于等于
  • .toBeCloseTo() - 浮点数比较
  • toBeGreaterThan、toBeGreaterThanOrEqual、toBeLessThan、toBeLessThanOrEqual

    test('two plus two', () => { 
    const value = 2 + 2; 
     expect(value).toBeGreaterThan(3); 
     expect(value).toBeGreaterThanOrEqual(3.5); 
     expect(value).toBeLessThan(5); 
     expect(value).toBeLessThanOrEqual(4.5);
    // toBe 和 toEqual 对于数字来说是一样的
     expect(value).toBe(4); 
     expect(value).toEqual(4); 
    

    .toBeCloseTo()

    对于比较浮点数的相等,应该使用 toBeCloseTo

    test('两个浮点数字相加', () => {
        const value = 0.1 + 0.2;        // 0.30000000000000004 
        expect(value).toBe(0.3);        // 这句会报错,因为 js 浮点数有舍入误差
        expect(value).toBeCloseTo(0.3); // 这句可以运行
    

    字符串匹配器

  • toMatch - 正则表达式的字符
  • .toHaveLength(number) - 判断一个有长度的对象的长度
  • toMatch

    正则表达式的字符

    test('there is no I in team', () => {
      expect('team').not.toMatch(/I/);
    test('but there is a "stop" in Christoph', () => {
      expect('Christoph').toMatch(/stop/);
    

    .toHaveLength(number)

    判断一个有长度的对象的长度

    expect([1, 2, 3]).toHaveLength(3);
    expect('abc').toHaveLength(3);
    expect('').not.toHaveLength(5);
    

    数组匹配器

  • .toContain(item) - 判断数组是否包含特定子项
  • .toContainEqual(item) - 判断数组中是否包含一个特定对象
  • .toContain

    判断数组是否包含特定子项

    const shoppingList = [
      'diapers',
      'kleenex',
      'trash bags',
      'paper towels',
      'beer',
    test('购物清单(shopping list)里面有啤酒(beer)', () => {
      expect(shoppingList).toContain('beer');
    

    .toContainEqual(item)

    可以判断数组中是否包含一个特定对象,类似 toEqual 与 toContain 的结合

    function myBeverages() {
        return [
            {delicious: true, sour: false},
            {delicious: false, sour: true}
    test('is delicious and not sour', () => {
        const myBeverage = {delicious: true, sour: false};
        expect(myBeverages()).toContainEqual(myBeverage);
    

    对象匹配器

  • .toMatchObject(object) - 判断一个对象嵌套的 key 下面的 value 类型
  • .toHaveProperty(keyPath, value) - 判断在指定的 path 下是否有这个属性
  • .toMatchObject(object)

    判断一个对象嵌套的 key 下面的 value 类型,需要传入一个对象。

    const houseForSale = {
      bath: true,
      bedrooms: 4,
      kitchen: {
        amenities: ['oven', 'stove', 'washer'],
        area: 20,
        wallColor: 'white',
    const desiredHouse = {
      bath: true,
      kitchen: {
        amenities: ['oven', 'stove', 'washer'],
        wallColor: expect.stringMatching(/white|yellow/),
    test('the house has my desired features', () => {
      expect(houseForSale).toMatchObject(desiredHouse);
    

    .toHaveProperty(keyPath, value)

    判断在指定的 path 下是否有这个属性,嵌套的 path 可以用 '.'分割,也可以用数组。

    // Object containing house features to be tested
    const houseForSale = {
      bath: true,
      bedrooms: 4,
      kitchen: {
        amenities: ['oven', 'stove', 'washer'],
        area: 20,
        wallColor: 'white',
    test('this house has my desired features', () => {
      // Simple Referencing
      expect(houseForSale).toHaveProperty('bath');
      expect(houseForSale).toHaveProperty('bedrooms', 4);
      expect(houseForSale).not.toHaveProperty('pool');
      // Deep referencing using dot notation
      expect(houseForSale).toHaveProperty('kitchen.area', 20);
      expect(houseForSale).toHaveProperty('kitchen.amenities', [
        'oven',
        'stove',
        'washer',
      expect(houseForSale).not.toHaveProperty('kitchen.open');
      // Deep referencing using an array containing the keyPath
      expect(houseForSale).toHaveProperty(['kitchen', 'area'], 20);
      expect(houseForSale).toHaveProperty(
        ['kitchen', 'amenities'],
        ['oven', 'stove', 'washer'],
      expect(houseForSale).toHaveProperty(['kitchen', 'amenities', 0], 'oven');
      expect(houseForSale).not.toHaveProperty(['kitchen', 'open']);
    

    自定义匹配器

    使用expect.extend将自己的匹配器添加到Jest。自定义匹配器需要返回一个包含两个key 的对象

    pass:false //‘布尔值’, message: () => 'message string' //‘函数,该函数返回一个提示信息’
    expect.extend({
      toBeDivisibleBy(received, argument) {
        const pass = received % argument == 0;
        if (pass) {
          return {
            message: () =>
              `expected ${received} not to be divisible by ${argument}`,
            pass: true,
        } else {
          return {
            message: () => `expected ${received} to be divisible by ${argument}`,
            pass: false,
    test('even and odd numbers', () => {
      expect(100).toBeDivisibleBy(2);
      expect(101).not.toBeDivisibleBy(2);
    

    这些帮助函数可以在自定义匹配器中的this中找到:

  • this.isNot
  • this.equals(a, b)
  • this.utils(matcherHint, printExpected and printReceived)
  • toThrow - 要测试的特定函数会在调用时抛出一个错误
  • .resolves 和 .rejects - 用来测试 promise
  • .toHaveBeenCalled() - 用来判断一个函数是否被调用过
  • .toHaveBeenCalledTimes(number) - 判断函数被调用过几次
  • toThrow

    要测试的特定函数会在调用时抛出一个错误

    function compileAndroidCode() {
      throw new ConfigError('you are using the wrong JDK');
    test('compiling android goes as expected', () => {
      expect(compileAndroidCode).toThrow();
      expect(compileAndroidCode).toThrow(ConfigError);
      // You can also use the exact error message or a regexp
      expect(compileAndroidCode).toThrow('you are using the wrong JDK');
      expect(compileAndroidCode).toThrow(/JDK/);
    

    .resolves 和 .rejects

    用来测试 promise

    //resolves test('resolves to lemon', () => { // make sure to add a return statement return expect(Promise.resolve('lemon')).resolves.toBe('lemon'); //rejects test('resolves to lemon', async () => { await expect(Promise.resolve('lemon')).resolves.toBe('lemon'); await expect(Promise.resolve('lemon')).resolves.not.toBe('octopus');

    .toHaveBeenCalled()

    .toHaveBeenCalled() 也有个别名是.toBeCalled(),用来判断一个函数是否被调用过。

    describe('drinkAll', () => {
      test('drinks something lemon-flavored', () => {
        const drink = jest.fn();
        drinkAll(drink, 'lemon');
        expect(drink).toHaveBeenCalled();
      test('does not drink something octopus-flavored', () => {
        const drink = jest.fn();
        drinkAll(drink, 'octopus');
        expect(drink).not.toHaveBeenCalled();
    

    .toHaveBeenCalledTimes(number)

    和 toHaveBeenCalled 类似,判断函数被调用过几次。

    test('drinkEach drinks each drink', () => {
      const drink = jest.fn();
      drinkEach(drink, ['lemon', 'octopus']);
      expect(drink).toHaveBeenCalledTimes(2);
    

    未整理部分

    lastCalledWith

    toBeCalledWith

    toHaveBeenCalledWith