Jest :测试类型或空值

kik*_*wie 4 javascript node.js jestjs

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

到目前为止我试过这个

  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
    };
  }
};
Run Code Online (Sandbox Code Playgroud)

在我的测试中

 expect(res.result.data).toBe(attendeeSchema);
Run Code Online (Sandbox Code Playgroud)

我也试过 tobeEqual 和其他东西....

我的测试没有通过

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

我不知道在这里做什么.. 如果有人有想法 谢谢

小智 9

之前给出的所有响应expect()在其实现中都未正确使用,因此它们并没有真正起作用。

您想要的是一个开玩笑的匹配器,它的工作原理类似于any()但接受空值并且expect()在其实现中不使用函数。您可以通过基本上复制原始any()实现(来自Jasmine)来将其作为扩展来实现,但在开头添加了一个空测试:

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)}`
    };
  }
});
Run Code Online (Sandbox Code Playgroud)

将上述内容放入.js文件中,然后使用 jestsetupFilesAfterEnv配置变量指向该文件。现在您可以运行您的测试,例如:

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

expect(object).toEqual(schema);

Run Code Online (Sandbox Code Playgroud)


小智 6

添加前两个答案,更常见的方法是将核心匹配器包装在 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
            };
      }
  }
});
Run Code Online (Sandbox Code Playgroud)


Dan*_*urt 6

您可以使用toBeOneOfjest -extended

安装后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),
};
Run Code Online (Sandbox Code Playgroud)
expect(res.result.data).toEqual(attendeeSchema);
Run Code Online (Sandbox Code Playgroud)


Kad*_*ath 4

我其实根本不了解 Jest,但我看了一下,因为我目前对代码测试感兴趣。

从我在Expect.extend 文档中看到的情况来看,您似乎使用了错误的方式。您当前正在向其提供调用的结果toBeTypeOrNull,例如birthDate: expect.extend(toBeTypeOrNull("Date")),不是函数本身。这可能会导致调用有一个未定义的参数,因为它是用 2 个参数声明的(received, argument)argument然后是未定义的,你不能expect.any(argument)在自定义函数中执行此操作。

从我在文档中看到的,您应该extend在开始时调用一个包含所有自定义函数的对象,以便稍后使用它们。尝试这段代码,如果出现问题,请毫不犹豫地发表评论:

更新:objectContaining有关和 之间的差异toMatchObject请参阅此答案

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()
  });
Run Code Online (Sandbox Code Playgroud)