Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Writing unit tests with Jest using test best practices

Writing unit tests with Jest using test best practices

Felipe Luiz Soares

June 09, 2020
Tweet

More Decks by Felipe Luiz Soares

Other Decks in Technology

Transcript

  1. Olá! • FE engineer • CA for 1 year and

    3 months • Brazil • Coffee, soccer, books, indie bands • Beer • Travel when possible (been safe for now)
  2. We will talk about • Testing the behaviour • Window

    object • Coverage • Tests as documentation • Unit tests structure • How to use Jest • Code
  3. We should • Avoid tests attached to the internals like

    “should defined variable x” • Avoid testing static methods • Avoid testing browser api’s such as listeners calls avoid
  4. What we should • Focus on functionality itself for most

    all the tests • Test public method responses • Always try to simulate the user interaction when it’s possible really focus
  5. Should we use it? • We decided to not use

    the window object • Feel free to clean the script and tests by mocking the window directly with Jest
  6. 100% of coverage • Behaviour tests should go through the

    entire code covering all the branches • Don’t use as the only metric to review approval • For old scripts, let’s try to cover at least the new features added or changed
  7. Since the tests are docs we should care about the

    structure of our own documentation
  8. • Use one describe for each behaviour • Use one

    describe for each branch • Break the tests into 3 steps Tests structure
  9. 1. Prepare all the data, variables, mocks 2. Run your

    test to trigger the behaviour like a click or an function call 3. Write the assertion expected for the behaviour tested Testing structure
  10. • We can mock global objets directly • We can

    continue to use the jasmine expectations • Let’s check a couple of examples Couple things before we start
  11. describe("When the script initiates”, () => { it("should trigger the

    fakeMethod”, () => { const fakeMethod = jest.fn(); callLater(fakeMethod); jest.runAllTimers(); expect(fakeMethod).toHaveBeenCalled(); }); });
  12. describe("When the script initiates”, () => { it("should trigger the

    fakeMethod”, () => { const fakeMethod = jest.fn(); callLater(fakeMethod); jest.runAllTimers(); expect(fakeMethod).toHaveBeenCalled(); }); });
  13. describe("When the script initiates”, () => { it("should trigger the

    fakeMethod”, () => { const fakeMethod = jest.fn(); callLater(fakeMethod); jest.runAllTimers(); expect(fakeMethod).toHaveBeenCalled(); }); });
  14. describe("When the script initiates”, () => { it("should trigger the

    fakeMethod”, () => { const fakeMethod = jest.fn(); callLater(fakeMethod); jest.runAllTimers(); expect(fakeMethod).toHaveBeenCalled(); }); });
  15. import classHelper from "class-helper—cool-lib"; jest.mock(“class-helper—cool-lib”); describe("When I am using the

    cool class library”, () => { it(“and I need to check if a class exists”, () => { classHelper.hasClass.mockResolvedValue(false); const el = document.createElement("div"); const result = checkClass(el); expect(result).toBe(false); }); });
  16. import classHelper from "class-helper—cool-lib"; jest.mock(“class-helper—cool-lib”); describe("When I am using the

    cool class library”, () => { it(“and I need to check if a class exists”, () => { classHelper.hasClass.mockResolvedValue(false); const el = document.createElement("div"); const result = checkClass(el); expect(result).toBe(false); }); });
  17. import classHelper from "class-helper—cool-lib"; jest.mock(“class-helper—cool-lib”); describe("When I am using the

    cool class library”, () => { it(“and I need to check if a class exists”, () => { classHelper.hasClass.mockResolvedValue(false); const el = document.createElement("div"); const result = checkClass(el); expect(result).toBe(false); }); });
  18. import classHelper from "class-helper—cool-lib"; jest.mock(“class-helper—cool-lib”); describe("When I am using the

    cool class library”, () => { it(“and I need to check if a class exists”, () => { classHelper.hasClass.mockResolvedValue(false); const el = document.createElement("div"); const result = checkClass(el); expect(result).toBe(false); }); });
  19. import classHelper from "class-helper—cool-lib"; jest.mock(“class-helper—cool-lib”); describe("When I am using the

    cool class library”, () => { it(“and I need to check if a class exists”, () => { classHelper.hasClass.mockResolvedValue(false); const el = document.createElement("div"); const result = checkClass(el); expect(result).toBe(false); }); });
  20. what if I need a true method from a mocked

    module -> const { addClass } = jest.requireActual(“class-helper—cool-lib”);
  21. describe("When the script initiates”, () => { describe(“and it’s succeed”,

    () => { it("should trigger the API call”, (done) => { const success = “Nothing to worry about here!”; const promise = Promise.resolve(success); const fetchMock = jest.fn().mockReturnValue(promise); const fakeAPIClient = { fetch: fetchMock }; callAsync(fakeAPIClient); fakeAPIClient().then((response) => { expect(response).toBe(success); done(); }); }); }); });
  22. describe("When the script initiates”, () => { describe(“and there is

    no error”, () => { it("should trigger the API call”, (done) => { const success = “Nothing to worry about here!”; const promise = Promise.resolve(success); const fetchMock = jest.fn().mockReturnValue(promise); const fakeAPIClient = { fetch: fetchMock }; callAsync(fakeAPIClient); fakeAPIClient().then((response) => { expect(response).toBe(success); done(); }); }); }); });
  23. describe("When the script initiates”, () => { describe(“and there is

    no error”, () => { it("should trigger the API call”, (done) => { const success = “Nothing to worry about here!”; const promise = Promise.resolve(success); const fetchMock = jest.fn().mockReturnValue(promise); const fakeAPIClient = { fetch: fetchMock }; callAsync(fakeAPIClient); fakeAPIClient().then((response) => { expect(response).toBe(success); done(); }); }); }); });
  24. describe("When the script initiates”, () => { describe(“and there is

    no error”, () => { it("should trigger the API call”, (done) => { const success = “Nothing to worry about here!”; const promise = Promise.resolve(success); const fetchMock = jest.fn().mockReturnValue(promise); const fakeAPIClient = { fetch: fetchMock }; callAsync(fakeAPIClient); fakeAPIClient().then((response) => { expect(response).toBe(success); done(); }); }); }); });
  25. describe("When the script initiates”, () => { describe(“and there is

    no error”, () => { it("should trigger the API call”, (done) => { const success = “Nothing to worry about here!”; const promise = Promise.resolve(success); const fetchMock = jest.fn().mockReturnValue(promise); const fakeAPIClient = { fetch: fetchMock }; callAsync(fakeAPIClient); fakeAPIClient().then((response) => { expect(response).toBe(success); done(); }); }); }); });
  26. describe("When the script initiates”, () => { describe(“and there is

    no error”, () => { it("should trigger the API call”, (done) => { const success = “Nothing to worry about here!”; const promise = Promise.resolve(success); const fetchMock = jest.fn().mockReturnValue(promise); const fakeAPIClient = { fetch: fetchMock }; callAsync(fakeAPIClient); fakeAPIClient().then((response) => { expect(response).toBe(success); done(); }); }); }); });
  27. Jest will wait until the done is called before finishing

    the test By default, Jest tests complete once they reach the end of their execution.
  28. describe("When the script initiates”, () => { describe(“and there is

    an error”, () => { it("should trigger the API call”, (done) => { const error = “Oh no, the house is on fire!”; const promise = Promise.rejects(error); const fetchMock = jest.fn().mockReturnValue(promise); const fakeAPIClient = { fetch: fetchMock }; callAsync(fakeAPIClient); fakeAPIClient().catch((response) => { expect(response).toBe(error); done(); }); }); }); });
  29. describe("When the script initiates”, () => { describe(“and there is

    an error”, () => { it("should trigger the API call”, (done) => { const error = “Oh no, the house is on fire!”; const promise = Promise.rejects(error); const fetchMock = jest.fn().mockReturnValue(promise); const fakeAPIClient = { fetch: fetchMock }; callAsync(fakeAPIClient); fakeAPIClient().catch((response) => { expect(response).toBe(error); done(); }); }); }); });