Published on

JestとRTLまとめ

Authors
  • avatar
    Name
    Kikusan
    Twitter

install

jestをreactで使用する。 他の使用方法は→https://jestjs.io/ja/docs/getting-started

npx create-react-app jest-rtl --template typescript

Jest

実行

npm testによってcreate-react-appでは実行できる。
Jestのwatchモードが起動し、ホットリロードで再テストされる。

構文

jestのtest(name: string, fn?: ProvidesCallback, timeout?: number): void;)メソッドを使用する。

matcher

expect(actualValue).matcher(expectValue)で記載する。

test('two plus two is four', () => {
  expect(2 + 2).toBe(4);
});

他のmatcher→https://jestjs.io/ja/docs/using-matchers

非同期

https://jestjs.io/ja/docs/asynchronous

test('the data is peanut butter', () => {
  return fetchData().then(data => {
    expect(data).toBe('peanut butter');
  });
});

test('the data is peanut butter', async () => {
  const data = await fetchData();
  expect(data).toBe('peanut butter');
});

test('the fetch fails with an error', async () => {
  expect.assertions(1);
  try {
    await fetchData();
  } catch (e) {
    expect(e).toMatch('error');
  }
});

// 上2つと同義

test('the data is peanut butter', async () => {
  await expect(fetchData()).resolves.toBe('peanut butter');
});

test('the fetch fails with an error', async () => {
  await expect(fetchData()).rejects.toMatch('error');
});

Before/After

https://jestjs.io/ja/docs/setup-teardown

describeはテストケースのグループ化に使用できる。

beforeAll(() => console.log('1 - beforeAll'));
afterAll(() => console.log('1 - afterAll'));
beforeEach(() => console.log('1 - beforeEach'));
afterEach(() => console.log('1 - afterEach'));

test('', () => console.log('1 - test'));

describe('Scoped / Nested block', () => {
  beforeAll(() => console.log('2 - beforeAll'));
  afterAll(() => console.log('2 - afterAll'));
  beforeEach(() => console.log('2 - beforeEach'));
  afterEach(() => console.log('2 - afterEach'));

  test('', () => console.log('2 - test'));
});

// 1 - beforeAll
// 1 - beforeEach
// 1 - test
// 1 - afterEach
// 2 - beforeAll
// 1 - beforeEach
// 2 - beforeEach
// 2 - test
// 2 - afterEach
// 1 - afterEach
// 2 - afterAll
// 1 - afterAll

Mock

https://jestjs.io/ja/docs/mock-functions

class MyClass {

  myMethod() {
    // 実際の実装
  }
}

const myFunc = (myClass: MyClass) => {
  myClass.myMethod();
}

test("mock test", () => {
  const MockedClass = jest.fn(() => ({
    myMethod: jest.fn(),
  }));
  
  // モッククラスのインスタンスを作成
  const instance = new MockedClass();
  
  // モックメソッドの呼び出し
  myFunc(instance);
  
  // モックメソッドが呼び出されたかを検証
  expect(instance.myMethod).toHaveBeenCalled();
})

React Testing Library

Jestと統合されており、Virtual DOMについての操作を行える。

Sample

各APIはチートシートにまとまっている。
Roleの仕様などはCore APIに書いてある。

import React from 'react'
import {rest} from 'msw'
import {setupServer} from 'msw/node'
import {render, fireEvent, screen} from '@testing-library/react'
import '@testing-library/jest-dom'
import Fetch from '../fetch'

const server = setupServer(
  rest.get('/greeting', (req, res, ctx) => {
    return res(ctx.json({greeting: 'hello there'}))
  }),
)

beforeAll(() => server.listen())
afterEach(() => server.resetHandlers())
afterAll(() => server.close())

test('loads and displays greeting', async () => {
  render(<Fetch url="/greeting" />)

  fireEvent.click(screen.getByText('Load Greeting'))

  await screen.findByRole('heading')

  expect(screen.getByRole('heading')).toHaveTextContent('hello there')
  expect(screen.getByRole('button')).toBeDisabled()
})

test('handles server error', async () => {
  server.use(
    rest.get('/greeting', (req, res, ctx) => {
      return res(ctx.status(500))
    }),
  )

  render(<Fetch url="/greeting" />)

  fireEvent.click(screen.getByText('Load Greeting'))

  await screen.findByRole('alert')

  expect(screen.getByRole('alert')).toHaveTextContent('Oops, failed to fetch!')
  expect(screen.getByRole('button')).not.toBeDisabled()
})