Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create tests or Mock DiscordJS Fetch/Catch using Jest

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.

like image 870
Cif Avatar asked Jun 05 '26 09:06

Cif


1 Answers

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);
  });
});
like image 184
Zsolt Meszaros Avatar answered Jun 06 '26 23:06

Zsolt Meszaros



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!