Jest 测试中遇到的 mock 生成 UUID 问题及解决方式

在前端开发中,我们经常会使用 Jest 进行测试,而其中的 mock 功能可以帮助我们模拟一些数据或者函数,方便我们进行测试。然而,当我们需要生成 UUID 的时候,就会发现 Jest 的 mock 无法直接生成 UUID,这就需要我们通过一些方法来解决这个问题。

UUID 的生成

UUID 全称通用唯一识别码,它是一个二进制长度为128位的数字,通常用32个16进制数表示,中间通过横线分隔。它可以用于标识单个计算机,也可以用于标识一组计算机或者其他的实体。在前端开发中,我们常常需要模拟这种唯一的 ID,来测试一些需要 ID 的功能,比如我们可能需要测试一个评论列表的组件,而这个组件需要每个评论都有唯一的 ID,这时就需要用到 UUID。

function generateUUID() {
  let d = new Date().getTime();
  const uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
    const r = (d + Math.random() * 16) % 16 | 0;
    d = Math.floor(d / 16);
    return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
  });
  return uuid;
}

上面的代码就是一个常见的生成 UUID 的函数。

Jest 中的 mock

Jest 中的 mock 功能可以让我们模拟某些数据或者函数的返回值。我们可以使用 jest.fn() 来创建一个 mock 函数,然后使用 mockImplementation 或者 mockReturnValue 来指定这个函数的返回值。

const fn = jest.fn();
fn.mockReturnValue(42);
console.log(fn()); // 42

我们还可以使用 jest.spyOn() 来 spy 一个对象的某个方法:

const obj = {
  foo() {
    return 42;
  },
};
const spy = jest.spyOn(obj, 'foo');
console.log(spy()); // 42

这样,我们就可以在测试中 mock 一个函数或者者一个对象的方法。

Jest 中的 mock 生成 UUID 的问题

我们使用上面的生成 UUID 的函数,来模拟返回一个 UUID。

jest.mock('../utils', () => ({
  generateUUID: jest.fn().mockReturnValue('fake-uuid'),
}));

这样,我们就成功的 mock 了我们的 generateUUID 函数,并且指定了它的返回值为 fake-uuid。然而,这样做有一个问题,jest.fn 的 mock 返回的是一个字符串,而不是我们希望的 UUID 的格式。

console.log(generateUUID()); // fake-uuid

这时,我们需要对产生的字符串进行格式化处理。我们可以在 mock 的返回值里写一个匿名函数,这个函数将会作为我们的 mock,我们在这个函数里面对字符串进行处理。

jest.mock('../utils', () => ({
  generateUUID: jest.fn().mockImplementation(() => {
    let d = new Date().getTime();
    const uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
      const r = (d + Math.random() * 16) % 16 | 0;
      d = Math.floor(d / 16);
      return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
    });
    return uuid;
  }),
}));

这样,我们就可以正常的使用 mock 了。

总结

在 Jest 中 mock 为我们测试提供了很大的便利,但是有时候我们需要模拟一些特殊的数据或者函数,需要注意是否需要对数据进行格式化或者处理。在这篇文章中,我们详细的说明了在 Jest 测试中 mock 生成 UUID 的问题,并提供了解决方式。希望对大家有帮助。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65bb2c27add4f0e0ff3cc4bb