创建使用Jest测试或模拟DiscordJS Fetch/Catch。

huangapple go评论68阅读模式
英文:

Create tests or Mock DiscordJS Fetch/Catch using Jest

问题

I have translated the non-code part of your text. Here it is:

"I have created a DiscordJS Bot and I am trying to implement automated tests using JestJS. Here's one of the functions I am trying to create tests with:

The problem that I can't solve right now is trying to create tests for both scenarios:

  • Retrieving a valid Guild (which returns a Guild Object).
  • Invalid Guild retrieval (which returns false).

Below is the current version of my sample.test.js file:

I found it difficult to mock the fetch/catch part of the program. Because fetch ends if the retrieval is successful and doesn't continue to the catch part unless it runs an error (like a try/catch would do). Upon running the tests, it displays the following:

Forgive me if my Jest implementation is wrong and would really appreciate everyone's assistance."

Please note that the code remains untranslated as requested. If you have any questions or need further assistance with the code, feel free to ask.

英文:

I have created a DiscordJS Bot and I am trying to implement automated tests using JestJS. Here's one of the functions I am trying to create tests with:

/**
 * @param {Object} client - Discord Client
*/
export const getSpecificGuild = async (client) => {
    let guild = await client.guilds.fetch(GUILD_ID).catch(() => { return false });

    if (!guild) return false;

    return guild;
}

The problem that I can't solve right now is trying to create tests for both scenarios:

  • Retrieving a valid Guild (which returns a Guild Object).
  • Invalid Guild retrieval (which returns false).

Below is the current version of my sample.test.js file:

describe('Test getSpecificGuild Function', () => {
    beforeEach(() => {
        jest.clearAllMocks();
    });

    const mockGuild = {
        ...
    }

    const mockClient = {
        guilds: {
            fetch: jest.fn().mockReturnValueOnce({
                catch: jest.fn().mockReturnValueOnce(false)
            })
        }
    }

    it(`should return the guild object if the guild doesn't exist.`, async () => {
        expect(await getSpecificGuild(mockClient)).toBe(false);
    });

    it(`should return the guild object if the guild does exist.`, async () => {
        expect(await getSpecificGuild(mockClient)).resolves.toBe(mockGuild);
    });
});

I found it difficult to mock the fetch/catch part of the program. Because fetch ends if the retrieval is successful and doesn't continue to the catch part unless it runs an error (like a try/catch would do). Upon running the tests, it displays the following:

✓ should return the guild object if the guild doesn't exist. (1 ms)
✕ should return the guild object if the guild does exist.

TypeError: Cannot read properties of undefined (reading 'catch')

let guild = await client.guilds.fetch(GUILD_ID).catch(() => { return false });
                                               ^

Forgive me if my Jest implementation is wrong and would really appreciate everyone's assistance.

答案1

得分: 4

以下是翻译好的内容:

那个`catch`是Promise实例上的一个方法你不应该对它进行模拟你只应该模拟`guilds.fetch()`

此外你的`getSpecificGuild()`函数目前不接受公会ID所以我对它进行了更新我认为`client.guilds.fetch()`永远不会返回假值所以你可以移除它

```js
export const getSpecificGuild = async (guildId, client) => {
  let guild = await client.guilds.fetch(guildId).catch(() => {
    return false;
  });

  return guild;
};

要模拟这个,你需要更新你的mockClient。你可以根据提供的公会ID改变fetch函数的行为,有条件地返回一个已解决的Promise或一个被拒绝的Promise。

describe('测试getSpecificGuild函数', () => {
  beforeEach(() => {
    jest.clearAllMocks();
  });

  const mockGuild = { ... };
  const VALID_GUILD_ID = '804214837842837';

  const mockClient = {
    guilds: {
      fetch: jest.fn().mockImplementation((guildId) => {
        // 有效的公会检索
        if (guildId === VALID_GUILD_ID) 
          return Promise.resolve(mockGuild);

        // 无效的公会检索
        else
          return Promise.reject(new Error('公会未找到'));
      }),
    },
  };

  it(`如果公会存在,应该返回公会对象。`, async () => {
    // 使用await时不需要使用"resolves.toBe()"
    expect(await getSpecificGuild(VALID_GUILD_ID, mockClient)).toBe(mockGuild);
  });

  it(`如果公会不存在,应该返回false。`, async () => {
    expect(await getSpecificGuild('12345', mockClient)).toBe(false);
  });
});

希望这能帮助你!如果有任何其他问题,请随时提问。

英文:

That catch is a method on a Promise instance, you should not mock that. You should only mock guilds.fetch().

Also, your getSpecificGuild() function doesn't accept a guild ID at the moment, so I updated it. And I don't think client.guilds.fetch() will ever return falsy values, so you can remove that too:

export const getSpecificGuild = async (guildId, client) => {
  let guild = await client.guilds.fetch(guildId).catch(() => {
    return false;
  });

  return guild;
};

To mock this, you need to update your mockClient. You could change the behaviour of the fetch function based on the provided guild ID and conditionally return either a resolved Promise or a rejected Promise.

describe('Test getSpecificGuild Function', () => {
  beforeEach(() => {
    jest.clearAllMocks();
  });

  const mockGuild = { ... };
  const VALID_GUILD_ID = '804214837842837';

  const mockClient = {
    guilds: {
      fetch: jest.fn().mockImplementation((guildId) => {
        // Valid guild retrieval
        if (guildId === VALID_GUILD_ID) 
          return Promise.resolve(mockGuild);

        // Invalid guild retrieval
        else
          return Promise.reject(new Error('Guild not found'));
      }),
    },
  };

  it(`should return the guild object if the guild does exist.`, async () => {
    // you don't need "resolves.toBe()"" with await
    expect(await getSpecificGuild(VALID_GUILD_ID, mockClient)).toBe(mockGuild);
  });

  it(`should return false if the guild doesn't exist.`, async () => {
    expect(await getSpecificGuild('12345', mockClient)).toBe(false);
  });
});

huangapple
  • 本文由 发表于 2023年6月12日 20:08:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/76456535.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定