====== Jest ======
ExpoでJestを使うには、jest-expoとjestの両方が必要。
[[https://github.com/expo/expo/tree/master/packages/jest-expo|jest-expo]]
===== インストール =====
npm i jest-expo --save-dev
npm i jest
===== package.json =====
//package.jsonに追加
"scripts": {
"test": "node_modules/.bin/jest"
},
"jest": {
"preset": "jest-expo",
"testEnvironment": "node" //必須ではない。jsdomを無効にしてテストを早くする
}
npm test
npm test -- --watch // ウォッチモードの場合
===== テスト =====
src/__tests__ フォルダの中にテストコードを配置する(ファイル名は何でもよい)
ファイル名の末尾を .test.js にする( src 内ならどこに置いてもよい)
==== エラー ====
Error: Cannot find module '[...pass...]\node_modules\jest\bin\jest.js'
jestがインストールされていない。
npm install jest
===== 使い方 =====
[[https://medium.com/@rickhanlonii/understanding-jest-mocks-f0046c68e53c|Understanding Jest Mocks]]
export const add = (a, b) => a + b;
export const subtract = (a, b) => b - a;
export const multiply = (a, b) => a * b;
export const divide = (a, b) => b / a;
import * as math from './src/math'
export const doAdd = (a, b) => math.add(a, b);
export const doSubtract = (a, b) => math.subtract(a, b);
export const doMultiply = (a, b) => math.multiply(a, b);
export const doDivide = (a, b) => math.divide(a, b);
==== 呼び出しの追跡 ====
import * as app from "./App"
import * as math from "./src/math"
describe(" Mock Function provides 3 features",()=>{
test("1.Capture calls 呼び出しを追跡する",()=>{
const mock = jest.fn()
let result = mock("foo")
expect(result).toBeUndefined()
expect(mock).toHaveBeenCalled()
expect(mock).toHaveBeenCalledTimes(1)
expect(mock).toHaveBeenCalledWith("foo")
})
})
==== 戻り値の設定 ====
import * as app from "./App"
import * as math from "./src/math"
describe(" Mock Function provides 3 features",()=>{
test("2-1.Set return values 戻値をセットする fn()",()=>{
const mock = jest.fn(() => "bar")
expect(mock("foo")).toBe("bar")
expect(mock).toHaveBeenCalledWith("foo")
})
})
==== 実装の変更 ====
import * as app from "./App"
import * as math from "./src/math"
describe(" Mock Function provides 3 features",()=>{
test("3-1.Change the implementation 実装を変更する mockImplementation()",()=>{
const mock = jest.fn().mockImplementation(() => "bar")
expect(mock("foo")).toBe("bar")
expect(mock).toHaveBeenCalledWith("foo")
})
test("3-2.Change the implementation 実装を変更する1回",()=>{
const mock = jest.fn().mockImplementationOnce(() => "bar")
expect(mock("foo")).toBe("bar")
expect(mock).toHaveBeenCalledWith("foo")
expect(mock("baz")).toBe(undefined)
expect(mock).toHaveBeenCalledWith("baz")
})
test("3-3.Change the implementation 実装を変更する promise",()=>{
const mock = jest.fn()
mock.mockResolvedValue("bar")
expect(mock("foo")).resolves.toBe("bar")
expect(mock).toHaveBeenCalledWith("foo")
})
})
==== 関数のモック ====
import * as app from "./App"
import * as math from "./src/math"
describe("モジュールと関数をモックする",()=>{
test("1.関数をモックする", () => {
math.add = jest.fn()
app.doAdd(1, 2)
expect(math.add).toHaveBeenCalledWith(1, 2)
});
})
==== モジュールのモック(jset.mock()) ====
import * as app from "./App"
import * as math from "./src/math"
//import と同じ階層で書く必要があるようだ。
//importもかかないとmahtが使えない。
//importした関数全てに math.xxx = jest.fn()している。
jest.mock("./src/math")
describe("モジュールと関数をモックする",()=>{
test("2.モジュールをモックする", () => {
app.doAdd(1, 2)
expect(math.add).toHaveBeenCalledWith(1, 2);
app.doSubtract(1, 2);
expect(math.subtract).toHaveBeenCalledWith(1, 2);
});
})
==== スパイ ====
describe("スパイ",()=>{
test("1.関数をスパイする", () => {
const addMock = jest.spyOn(math, "add");
//実装は変わらない
expect(app.doAdd(1, 2)).toEqual(3);
//しかし追跡できる
expect(addMock).toHaveBeenCalledWith(1, 2);
});
test("2.スパイしている関数の実装を変更して戻す", () => {
const addMock = jest.spyOn(math, "add");
// 実装を変更する
addMock.mockImplementation(() => "mock");
expect(app.doAdd(1, 2)).toEqual("mock");
// 元に戻す
addMock.mockRestore();
expect(app.doAdd(1, 2)).toEqual(3);
});
})
==== スパイは基本のfn()の組み合わせ ====
describe("スパイ",()=>{
test("スパイは基本のfn()の組み合わせ", () => {
// オリジナル実装をバックアップ
const originalAdd = math.add;
// オリジナル実装でモックする
math.add = jest.fn(originalAdd);
// オリジナル実装のスパイができるようになる
expect(app.doAdd(1, 2)).toEqual(3);
expect(math.add).toHaveBeenCalledWith(1, 2);
// 実装を変更する
math.add.mockImplementation(() => "mock");
expect(app.doAdd(1, 2)).toEqual("mock");
expect(math.add).toHaveBeenCalledWith(1, 2);
// オリジナル実装に戻す
math.add = originalAdd;
expect(app.doAdd(1, 2)).toEqual(3);
})
})