Open6

Jest 逆引き テストケース

ピン留めされたアイテム
nus3nus3

jestのロゴ

下記のテンプレートをベースにJestのテストパターンをスクラップに書いてきやす

他の方の投稿も許可してるので、コメントでも新しいテストケース(Jest単体のでも、Testing Libraryを使ったのでも、なんでも)でも書いてもらえるとうれしいデス!

nus3nus3

テンプレート

必要じゃない項目は削ってもらって大丈夫です〜
もしくは改善案とかあればコメントもらえると喜びます

# タイトル

:::details 環境
```json
```
:::

:::details テスト対象コード
```typescript
```
:::

## テストコード

```typescript

```

## 参考記事(あれば)
- []()
- []()
nus3nus3

classの非同期メソッドをモックしたテスト

環境
"jest": "26.6.3",
テスト対象コード
export class FooClass {
  public foo(): Promise<string> {
    return new Promise<string>((resolve) => {
      resolve('foo')
    })
  }
}

export const barMethod = async (): Promise<string> => {
  const f = new FooClass()
  const value = await f.foo()

  return `${value}bar`
}

テストコード

describe('FooClass test', () => {
  afterEach(() => {
    jest.clearAllMocks()
  })

  afterAll(() => {
    jest.restoreAllMocks()
  })

  test('barMethod test', async () => {
    const mockReturnValue = 'baz'

    const mockFooClass = jest
      .spyOn(FooClass.prototype, 'foo')
      .mockResolvedValue(mockReturnValue)

    const result = await barMethod()

    expect(mockFooClass).toHaveBeenCalledTimes(1)
    expect(result).toBe('bazbar')
  })
})

参考記事(あれば)

nus3nus3

Next.jsのuseRouterのpushをモックしたテスト

環境
"@testing-library/jest-dom": "5.14.1",
"@testing-library/react": "12.0.0",
"jest": "26.6.3",
"next": "11.1.2",
"react": "17.0.2",
"react-dom": "17.0.2",
テスト対象コード
import { useRouter } from 'next/router'
import { FC } from 'react'

export const Button: FC = () => {
  const { push } = useRouter()

  return (
    <button
      type="button"
      onClick={() => {
        push('/')
      }}
    >
      label
    </button>
  )
}

テストコード

import { fireEvent, render } from '@testing-library/react'

import { Button } from './foo'

const useRouter = jest.spyOn(require('next/router'), 'useRouter')
const push = jest.fn()
useRouter.mockImplementation(() => {
  return { push }
})

describe('Button component test', () => {
  afterEach(() => {
    jest.clearAllMocks()
  })

  afterAll(() => {
    jest.restoreAllMocks()
  })

  test('Buttonをクリックした際にuseRouterのpushが正しく呼ばれているか', () => {
    const { getByText } = render(<Button />)

    const label = 'label'
    fireEvent.click(getByText(label))

    expect(push).toHaveBeenCalledTimes(1)

    const path = '/'
    expect(push).toBeCalledWith(path)
  })
})
nus3nus3

console.errorの中身をテストする

環境
"jest": "26.6.3",
テスト対象コード
export const foo = (isError: boolean): string => {
  if (isError) {
    console.error('Oops, seems like an error.')
    return ''
  }

  return 'foo'
}

テストコード

import { foo } from './foo'

describe('foo method test', () => {
  afterEach(() => {
    jest.clearAllMocks()
  })

  afterAll(() => {
    jest.restoreAllMocks()
  })

  test('output console error if isError is true', () => {
    const consoleErrorMock = jest.fn()
    jest.spyOn(console, 'error').mockImplementationOnce(consoleErrorMock)

    const result = foo(true)

    expect(consoleErrorMock).toHaveBeenCalledTimes(1)
    const errorMsg = 'Oops, seems like an error.'
    expect(consoleErrorMock).toHaveBeenCalledWith(errorMsg)
    expect(result).toBe('')
  })
})

参考記事(あれば)

nus3nus3

非同期でerrorをthrowするメソッドのテスト

環境
"jest": "26.6.3",
テスト対象コード
export class FooClass {
  public foo(): Promise<string> {
    return new Promise<string>((resolve) => resolve('foo'))
  }
}

export const bar = async (): Promise<string> => {
  const fooClass = new FooClass()
  const f = await fooClass.foo().catch((error) => {
    throw new Error(error)
  })
  return f
}

テストコード

import { bar, FooClass } from './foo'

describe('bar method test', () => {
  afterEach(() => {
    jest.clearAllMocks()
  })

  afterAll(() => {
    jest.restoreAllMocks()
  })

  test('should throw error', async () => {
    const errMsg = 'Oops, seems like an error.'

    const fooMock = jest
      .spyOn(FooClass.prototype, 'foo')
      .mockRejectedValue(errMsg)

    await expect(bar()).rejects.toThrowError(new Error(errMsg))
    expect(fooMock).toHaveBeenCalledTimes(1)
  })
})