NodeJS Jest:测试type或null

kokeuurv  于 2023-08-04  发布在  Node.js
关注(0)|答案(8)|浏览(124)

我有一个测试,我想测试我接收到的对象值类型是否与模式匹配。问题是,对于某些键,我可能会收到一些东西或空
到目前为止我试过这个

const attendeeSchema = {
  birthDate: expect.extend(toBeTypeOrNull("Date")),
  contact: expect.extend(toBeTypeOrNull(String)),
  createdAt: expect.any(Date),
  firstName: expect.any(String),
  id: expect.any(Number),
  idDevice: expect.extend(toBeTypeOrNull(Number)),
  information: expect.extend(toBeTypeOrNull(String)),
  lastName: expect.any(String),
  macAddress: expect.extend(toBeTypeOrNull(String)),
  updatedAt: expect.any(Date),
  // state: toBeTypeOrNull()
};

    const toBeTypeOrNull = (received, argument) => {
  const pass = expect(received).toEqual(expect.any(argument));
  if (pass || received === null) {
    return {
      message: () => `Ok`,
      pass: true
    };
  } else {
    return {
      message: () => `expected ${received} to be ${argument} type or null`,
      pass: false
    };
  }
};

字符串
在我的测试中

expect(res.result.data).toBe(attendeeSchema);


我也试过平等和其他东西。
我的考试没有通过

TypeError: any() expects to be passed a constructor function. Please pass one or use anything() to match any object.


我不知道该怎么办。如果有人有想法谢谢

new9mtju

new9mtju1#

前面给出的所有响应在其实现中都不正确地使用了expect(),因此它们实际上并不起作用。
您需要的是一个像any()一样工作的jest匹配器,但它接受空值,并且在其实现中不使用expect()函数。您可以通过复制原始的any()实现(来自Jasmine)来实现此扩展,但在开始时添加了null测试:

expect.extend({
  nullOrAny(received, expected) {
    if (received === null) {
      return {
        pass: true,
        message: () => `expected null or instance of ${this.utils.printExpected(expected) }, but received ${ this.utils.printReceived(received) }`
      };
    }

    if (expected == String) {
      return {
        pass: typeof received == 'string' || received instanceof String,
        message: () => `expected null or instance of ${this.utils.printExpected(expected) }, but received ${ this.utils.printReceived(received) }`
      };        
    }

    if (expected == Number) {
      return {
        pass: typeof received == 'number' || received instanceof Number,
        message: () => `expected null or instance of ${this.utils.printExpected(expected)}, but received ${this.utils.printReceived(received)}`
      };
    }

    if (expected == Function) {
      return {
        pass: typeof received == 'function' || received instanceof Function,
        message: () => `expected null or instance of ${this.utils.printExpected(expected)}, but received ${this.utils.printReceived(received)}`
      };
    }

    if (expected == Object) {
      return {
        pass: received !== null && typeof received == 'object',
        message: () => `expected null or instance of ${this.utils.printExpected(expected)}, but received ${this.utils.printReceived(received)}`
      };
    }

    if (expected == Boolean) {
      return {
        pass: typeof received == 'boolean',
        message: () => `expected null or instance of ${this.utils.printExpected(expected)}, but received ${this.utils.printReceived(received)}`
      };
    }

    /* jshint -W122 */
    /* global Symbol */
    if (typeof Symbol != 'undefined' && this.expectedObject == Symbol) {
      return {
        pass: typeof received == 'symbol',
        message: () => `expected null or instance of ${this.utils.printExpected(expected)}, but received ${this.utils.printReceived(received)}`
      };
    }
    /* jshint +W122 */

    return {
      pass: received instanceof expected,
      message: () => `expected null or instance of ${this.utils.printExpected(expected)}, but received ${this.utils.printReceived(received)}`
    };
  }
});

字符串
将上面的内容放入一个.js文件中,然后用jest setupFilesAfterEnv配置变量指向该文件。现在你可以像这样运行测试:

const schema = {
  person: expect.nullOrAny(Person),
  age: expect.nullOrAny(Number)
};

expect(object).toEqual(schema);

jhiyze9q

jhiyze9q2#

在前面两个答案的基础上,一种更常见的方法是将核心匹配器 Package 在try/catch块中

expect.extend({
  toBeTypeOrNull(received, classTypeOrNull) {
      try {
          expect(received).toEqual(expect.any(classTypeOrNull));
          return {
              message: () => `Ok`,
              pass: true
            };
      } catch (error) {
          return received === null 
            ? {
                  message: () => `Ok`,
                  pass: true
              }
            : {
                  message: () => `expected ${received} to be ${classTypeOrNull} type or null`,
                  pass: false
            };
      }
  }
});

字符串

9rnv2umw

9rnv2umw3#

您可以使用jest-extended中的toBeOneOf
安装jest-extended以使expect.toBeOneOf可用后:

const attendeeSchema = {
  birthDate: expect.toBeOneOf([expect.any(Date), null]),
  contact: expect.toBeOneOf([expect.any(String), null]),
  createdAt: expect.any(Date),
  firstName: expect.any(String),
  id: expect.any(Number),
  idDevice: expect.toBeOneOf([expect.any(Number), null]),
  information: expect.toBeOneOf([expect.any(String), null]),
  lastName: expect.any(String),
  macAddress: expect.toBeOneOf([expect.any(String), null]),
  updatedAt: expect.any(Date),
};

个字符

uqdfh47h

uqdfh47h4#

实际上,我根本不知道Jest,但我看了一下,因为代码测试目前对我很感兴趣。
从我在expect.extend文档中看到的内容来看,您似乎使用了错误的方法。你现在给它的是调用toBeTypeOrNull的结果,例如在birthDate: expect.extend(toBeTypeOrNull("Date")),中,而不是函数本身。这可能会导致调用有一个未定义的参数,因为它是用2个参数(received, argument)声明的。然后argument是未定义的,你不能在你的自定义函数中执行expect.any(argument)
从我在文档中看到的来看,你应该在一开始就用一个包含所有自定义函数的对象调用extend,这样你就可以在以后使用它们。试试这段代码,如果出现问题,请不要犹豫:

更新:objectContainingtoMatchObject的区别,see this answer

expect.extend({
  toBeTypeOrNull(received, argument) {
    const pass = expect(received).toEqual(expect.any(argument));
    if (pass || received === null) {
      return {
        message: () => `Ok`,
        pass: true
      };
    } else {
      return {
        message: () => `expected ${received} to be ${argument} type or null`,
        pass: false
      };
    }
  }
});

//your code that starts the test and gets the data
  expect(res.result.data).toMatchObject({
    birthDate: expect.toBeTypeOrNull(Date),
    contact: expect.toBeTypeOrNull(String),
    createdAt: expect.any(Date),
    firstName: expect.any(String),
    id: expect.any(Number),
    idDevice: expect.toBeTypeOrNull(Number),
    information: expect.toBeTypeOrNull(String),
    lastName: expect.any(String),
    macAddress: expect.toBeTypeOrNull(String),
    updatedAt: expect.any(Date),
    // state: toBeTypeOrNull()
  });

字符串

qlvxas9a

qlvxas9a5#

我决定使用一个通用的“any of”来代替特定的处理程序:

expect.extend({
  toEqualAnyOf(received: any, argument: any[]) {
    const found = argument.some((eqItem) => {
      // undefined
      if (typeof eqItem === 'undefined' && typeof received === 'undefined') {
        return true;
      }
      // null
      if (eqItem === null && received === null) {
        return true;
      }
      // any expect.<any> or direct value
      try {
        expect(received).toEqual(eqItem);
        return true;
      } catch (e) {
        return false;
      }
    });
    return found
      ? {
          message: () => 'Ok',
          pass: true,
        }
      : {
          message: () => `expected ${received} to be any of ${argument}`,
          pass: false,
        };
  },
});

module.exports = { expect };

字符串
它可以这样使用:

const userImageSchema = {
  displayName: expect.any(String),
  // null or undefined or part of structure or instance of a class
  image: expect.toEqualAnyOf([
    null,
    undefined,
    expect.objectContaining({
      type: 'Buffer',
      data: expect.any(Array),
    }),
    expect.any(ImageClass),
  ]),
  orgs: expect.any(Array),
};

yv5phkfx

yv5phkfx6#

我正在寻找一些东西来验证任何类型或null,并遇到了这个答案,这是95%的权利。问题出在这一行,因为在尝试比较nullargument时,预期失败。

const pass = expect(received).toEqual(expect.any(argument));

字符串
作为奖励,我创建了一个toBeObjectContainingOrNull。下面是我的代码:

const expect = require("expect");

const okObject = {
    message: () => "Ok",
    pass: true
};

expect.extend({
    toBeTypeOrNull(received, argument) {
        if (received === null)
            return okObject;
        if (expect(received).toEqual(expect.any(argument))) {
            return okObject;
        } else {
            return {
                message: () => `expected ${received} to be ${argument} type or null`,
                pass: false
            };
        }
    },
    toBeObjectContainingOrNull(received, argument) {
        if (received === null)
            return okObject;

        const pass = expect(received).toEqual(expect.objectContaining(argument));
        if (pass) {
            return okObject;
        } else {
            return {
                message: () => `expected ${received} to be ${argument} type or null`,
                pass: false
            };
        }
    }
});

module.exports = { expect };


然后你可以使用toBeObjectContainingOrNull如下:

const userImageSchema = {
    displayName: expect.any(String),
    image: expect.toBeObjectContainingOrNull({
        type: "Buffer",
        data: expect.any(Array)
    }),
    orgs: expect.any(Array)
};


希望能帮上忙。

rhfm7lfc

rhfm7lfc7#

已经在expect-more-jest中实现
这将工作:

require('expect-more-jest');

test("test 1 2 3", async () => {
    expect(null).toBeNullableOf(String)
    expect('String').toBeNullableOf(expect.any(String))
    expect('String').not.toBeNullableOf(expect.any(Number))
    expect('String').toBeNullableOf('String')
    expect(1).toBeNullableOf(expect.any(Number))
    expect(1).not.toBeNullableOf(expect.any(String))
    expect(1).not.toBeNullableOf(String)
}

字符串

o7jaxewo

o7jaxewo8#

我的解决方案是在运行'expect'语句之前简单地修改输入数据,例如:
schema值应该如下所示:

const attendeeSchema = {
  ....
  contact: true,
};

字符串
在test中,在expect之前,我们修改输入数据以检查值是string还是null:

res.result.data = res.result.data.map(i => ({...i, contact: typeof i.contact === 'string' || i.contact === null}))
expect(res.result.data).toBe(attendeeSchema);

相关问题