Skip to content

HOW TO: Unit Testing for Components

Ritchelle Grace Posadas edited this page Apr 11, 2020 · 5 revisions

Unit Testing for Components

Testing Stack

We currently use:

  • Jest
  • Enzyme

1. Testing File Structure

Say you have your component ready. The very first thing you want to do is set up a test suite for good practices.

  • describe: test suite encompassing individual tests
  • it: individual tests
describe("Test suite component", () => {
  it("description/expectation of your test #1", () => {
    ...
  });

  it("description/expectation of your test #2", () => {
    ...
  });
  ...
});

2. What Do I Even Test?

  • You can see multiple example unit tests in our tests folder.
  • You may be asking yourself: what am I even supposed to be testing anyway?
  • Jest has you covered! Run npm test --coverage and Jest will tell you which lines you need to cover. For example, this code snippet is telling you to test the uncovered lines in order to reach 100% code coverage.
-------------------------------------|---------|----------|---------|---------|-----------------------------------------------
File                                 | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
-------------------------------------|---------|----------|---------|---------|-----------------------------------------------
All files                            |    56.9 |    32.14 |   26.92 |   58.93 |
 components/building-highlights      |   63.64 |    66.67 |      40 |   63.64 |
  building-highlights.component.tsx  |   63.64 |    66.67 |      40 |   63.64 | 23,24,41,49
 components/building-information     |    38.1 |     7.14 |   23.08 |    38.1 |
  building-information.component.tsx |    38.1 |     7.14 |   23.08 |    38.1 | 67,68,73,75,96,98,100,115,123,124,145,153,154
 components/building-location        |     100 |      100 |     100 |     100 |
  building-location.component.tsx    |     100 |      100 |     100 |     100 |
 components/campus-toggle            |   66.67 |       50 |   33.33 |   66.67 |

3. Snapshot Testing

Snapshot testing is important to us as it also helps us cover test coverage. You can view them as UI unit tests. This is an example of a snapshot test:

// Important modules to import for snapshot testing
import React from "react";
import renderer from "react-test-renderer"

// The component you want to render
import BuildingLocation from "../src/components/building-location/building-location.component";

describe("BuildingLocation component", () => {
  it("renders snapshot correctly", () => {
    const tree = renderer.create(<BuildingLocation />).toJSON();
    expect(tree).toMatchSnapshot();
  });
})

4. Functional Unit Tests

Below is a code snippet explaining the common structure of setting up a Jest unit test supported by Enzyme.

Notes:

  • When performing unit tests on a component, it might depend on external functions, contexts, etc. These external dependencies must be mocked so that we only test the relevant component. Afterward, we can check whether these dependencies have been used/called as expected.
import React from "react";
import CampusToggle from "../src/components/campus-toggle/campus-toggle.component";
import { shallow } from "enzyme";

it("onSGWPressButton: on button press, check if isSGW state hook is true", () => {
    // jest.fn() enables you to mock a function
    // mockOnCampusToggle then obtains a property called `.mock` which enables you to test a variety
    // of function functionalities 
    // See more here: https://jestjs.io/docs/en/mock-functions.html#mock-property
    const mockOnCampusToggle = jest.fn();

    // Shallow allows you to render a shallow copy of a react component as an object 
    // in memory instead of the DOM. This allows us to easily examine the rendered components
    // wrapper allows us to easily examine the rendered components
    // In this case, we are rendering a shallow copy of the CampusToggle functional component
    const wrapper = shallow(
      <CampusToggle onCampusToggle={mockOnCampusToggle} />
    );

    // wrapper.find() enables you to find the elements you want to test/manipulate
    // See more here: https://enzymejs.github.io/enzyme/docs/api/ShallowWrapper/find.html
    const button = wrapper.find("View TouchableHighlight").at(0);
    button.simulate("press");

    // Assertion tests through Jest expect
    expect(mockOnCampusToggle).toHaveBeenCalledTimes(1);
    expect(mockOnCampusToggle.mock.calls[0][0]).toBe(
      getCampus(CampusId.SGW).region
    );

Handy Links for Unit Testing

5. Gotcha's and Common Questions

Testing Functional Classes with React Hooks

  • Is your functional component using react hooks? Ex: useState(), useEffect(), etc.
  • This basically means that you have a stateless functional component, barring you from using the most useful tools from Enzyme such as wrapper.instance(), wrapper.state(), etc.
  • The only solution now is to test the SIDE-EFFECTS which the state triggers.
  • Example case: A boolean value triggers the styling of our campus toggles. Instead of checking the react state hook, check the difference in stylings instead before and after the hook is triggered.

^^^ ONCE TASK-12 MERGED, TO-DO: update link to develop branch

Clone this wiki locally