Test mocked try and catch with Vitest in same file

29 views Asked by At

I'm mocking an external library (public-ip). I would test my implementation - I'm using Vitest as test runner:

const getPublicIp = async (): Promise<string> => {
  try {
    return await publicIpv4();
  } catch (error) {
    logger.error("Unable to fetch public IP. The error was %s", error);
    return ""; // In caso di errore, ritorna una stringa vuota
  }
};

At the moment I'm using two different test files:

  • getPublic.test.ts:

    import { describe, expect, it, vi } from "vitest";
    import { getPublicIp } from "../../utils/utils";
    
    /**
     * Mock the external library
     */
    vi.mock("public-ip", async (importOriginal) => {
      const mod = await importOriginal();
      if (typeof mod === "object" && mod !== null) {
        return {
          ...mod,
          publicIpv4: vi.fn(() => "1.2.3.4"),
        };
      }
      return {
        publicIpv4: vi.fn(() => "1.2.3.4"),
      };
    });
    
    describe("Test external utils", () => {
      it("Can return a public IP", async () => {
        const expectedResult = "1.2.3.4";
        const result = await getPublicIp();
        expect(result).toBe(expectedResult);
      });
    });
    
    

    and

  • getPublicIp.error.test.ts:

    import { describe, expect, it, vi } from "vitest";
    import { getPublicIp } from "../../utils/utils";
    
    /**
     * Mock the external library
     */
    vi.mock("public-ip", async (importOriginal) => {
      const mod = await importOriginal();
      if (typeof mod === "object" && mod !== null) {
        return {
          ...mod,
          publicIpv4: vi.fn(() => {
            throw new Error("Failed to fetch public IP. Error thrown from Vitest");
          }),
        };
      }
      return {
        publicIpv4: vi.fn(() => {
          throw new Error("Failed to fetch public IP. Error thrown from Vitest");
        }),
      };
    });
    
    describe("Test external utils", () => {
      it("Can handles error when fetching public IP", async () => {
        const expectedResult = "";
        const result = await getPublicIp();
        expect(result).toBe(expectedResult);
      });
    });
    
    

I would like to merge both files, with a test returning the success and another one returing the error.

Is it possible?

1

There are 1 answers

0
sineverba On

With the help of jonrsharpe, I can merge both tests:

import { publicIpv4 } from "public-ip";
import { describe, expect, it, vi } from "vitest";

import { getPublicIp } from "../../utils/utils";

vi.mock("public-ip");

describe("Test external utils", () => {
  it("Can return a public IP", async () => {
    const expectedResult = "1.2.3.4";
    vi.mocked(publicIpv4).mockResolvedValue(expectedResult);
    const result = await getPublicIp();
    expect(result).toBe(expectedResult);
  });
  it("Can handles error when fetching public IP", async () => {
    const expectedResult = "";
    vi.mocked(publicIpv4).mockRejectedValue(
      new Error("Failed to fetch public IP. Error thrown from Vitest"),
    );
    const result = await getPublicIp();
    expect(result).toBe(expectedResult);
  });
});