Jest - arthur791004/notes GitHub Wiki

Basic

Matchers

  • Truthiness
    • toBeNull matches only null
    • toBeUndefined matches only undefined
    • toBeDefined is the opposite of toBeUndefined
    • toBeTruthy matches anything that an if statement treats as true
    • toBeFalsy matches anything that an if statement treats as false
  • Floating point equality: toBeCloseTo
  • String: toMatch
  • Arrays: toContain
  • Exceptions: toThrow

Asynchronous

  • Callbacks: use a single argument called done
  • Promises
    • just returns a Promise
    • resolves / rejects
      • return expect(fetchData()).resolves.toBe('peanut butter');
      • return expect(fetchData()).rejects.toMatch('error');
  • Async/Await: just use the async keyword in front of the function

Setup and Teardown

  • Repeating Setup: beforeEach / afterEach
  • One-Time Setup: beforeAll / afterAll
  • Scoping: the before and after blocks only apply to the tests within that describe block.

Mock Functions

  • Mock Function: jest.fn()
  • .mock Properties
  • Mock Return Values: mockReturnValueOnce / mockReturnValue
  • Mock Implementations
    • const mockFunc = jest.fn(() => {})
    • mockImplementation
      import foo from '../foo';
      
      jest.mock(foo);
      
      foo.mockImplementation(() => 7012);
      
    • mockImplementationOnce
    • mockReturnThis: const value = jest.fn().mockReturnThis()
  • Custom Matchers
    • toBeCalled
    • toBeCalledWith
    • lastCalledWith
  • spyOn
    • If you want to overwrite the original function, you can use:
      jest.spyOn(object, methodName)
        .mockImplementation(() => customImplementation);
      
      // or
      
      object[methodName] = jest.fn(() => customImplementation);
      
    • Example
      const video = require('./video');
      
      test('plays video', () => {
        const spy = jest.spyOn(video, 'play');
        const isPlaying = video.play();
      
        expect(spy).toHaveBeenCalled();
        expect(isPlaying).toBe(true);
      
        spy.mockReset();
        spy.mockRestore();
      });
      

Advanced

Snapshot Testing

  • Create Snapshot: toMatchSnapshot
  • Update Snapshot: jest --updateSnapshot

Testing React Apps

  • Snapshot Testing Example
    // Link.react-test.js
    import React from 'react';
    import Link from '../Link.react';
    import renderer from 'react-test-renderer';
    
    test('Link changes the class when hovered', () => {
      const component = renderer.create(
        <Link page="http://www.facebook.com">Facebook</Link>
      );
      let tree = component.toJSON();
      expect(tree).toMatchSnapshot();
    
      // manually trigger the callback
      tree.props.onMouseEnter();
      // re-rendering
      tree = component.toJSON();
      expect(tree).toMatchSnapshot();
    
      // manually trigger the callback
      tree.props.onMouseLeave();
      // re-rendering
      tree = component.toJSON();
      expect(tree).toMatchSnapshot();
    });
    
  • DOM Testing
    • use Enzyme or React's TestUtils
    • shallow
      import React from 'react';
      import {shallow} from 'enzyme';
      import CheckboxWithLabel from '../CheckboxWithLabel';
      
      test('CheckboxWithLabel changes the text after click', () => {
        // Render a checkbox with label in the document
        const checkbox = shallow(
          <CheckboxWithLabel labelOn="On" labelOff="Off" />
        );
      
        expect(checkbox.text()).toEqual('Off');
      
        checkbox.find('input').simulate('change');
      
        expect(checkbox.text()).toEqual('On');
      });
      

An Async Example

  • create a manual mock for our request.js module in the __mocks__ folder.
  • call jest.mock('../request') to tell Jest to use our manual mock

Timer Mocks

  • setTimeout, setInterval, clearTimeout, clearInterval
    • jest.useFakeTimers();: mocks out setTimeout and other timer functions with mock functions.
  • Run All Timers: jest.runAllTimers();
  • Run Pending Timers (Recursively set timers): jest.runOnlyPendingTimers();
  • Run Timers to Time: jest.runTimersToTime(msToRun)

Manual Mocks

Using With Webpack

Migrating to Jest

Testing Other Frameworks

Troubleshooting

各部分測試重點與方法

Services

Actions

  • 執行 action 後,返回預期的 object (type + payload)

Reducers

  • 輸入 initial state 和 action 後,返回預期的 state
  • 連續輸入 state 和 action 後,與 snapshots 相符

Epics

Containers

  • Container 與其 Component 都有被 render 出來
    • 需用 <Provider> 包起來
  • 被 Mock 的 Component 有被 call 一次
  • 準備假資料,用 Provider 包起來,傳入 Context
    • 自己 mock createStore

Components

  • Snapshot 測試
  • Simulate 行為測試

Router

  • params/path 相符
  • property 相符
  • Component 相符

Selectors

  • 計算結果與預期相符
  • 輸入相同的職,不會重新計算

Utils

Loaders

Notes

  • toBe v.s toEqual
    • toBe: uses === to test exact equality
    • toEqual: check the value of an object
  • jest.spyOn
  • ...

Reference

⚠️ **GitHub.com Fallback** ⚠️