จากบทความที่แล้ว ที่เป็นเรื่องของ mock function ใน jest

หากเราต้องการที่จะจำลองการใช้งานของฟังก์ชั่นภายในไฟล์เดียวกัน เราจะต้องใช้งาน spy
แทนการใช้งาน mock
โดยบทความนี้เราจะมาพูดถึงการใช้งาน spy
ใน jest กัน
Spy
อธิบายเกี่ยวกับ spy แบบง่ายๆ เลย มันก็เป็นเหมือนการสอดส่อง ฟังก์ชั่นที่เราต้องการจะจับตามันและตรวจสอบว่า...
- ฟังก์ชั่นถูกเรียกหรือไม่
- ฟังก์ชั่นถูกเรียกกี่ครั้ง
- ตรวจสอบ arguments ที่ส่งไปยังฟังก์ชั่น
- ตรวจสอบค่าที่ return จากฟังก์ชั่น
รวมถึง mocking return ฟังก์ชั่นภายในไฟล์เดียวกันกับไฟล์ที่ต้องการทดสอบ
เราลองมาดูตัวอย่างกันเลย
Spy Self File
export const doubleSum = (x: number, y: number): number => {
const sum = add(x, y)
return x + y + sum
}
export const add = (x: number, y: number): number => {
return x + y
}
calculate.ts
หากเราต้องการทดสอบฟังก์ชั่น add()
ได้มีการถูกเรียกใช้งานหรือไม่ เราจะเขียนการทดสอบได้ดังนี้
import * as calculate from './calculate'
describe('spy self', () => {
it('Should be called add when call doubleSum', () => {
const x = 2
const y = 2
const mathAddSpy = jest.spyOn(calculate, 'add')
calculate.doubleSum(x, y)
expect(mathAddSpy).toHaveBeenCalled()
})
})
calculate.test.ts
หากต้องการที่จะทดสอบว่าฟังก์ชั่น add()
มีการเรียกใช้งานกี่ครั้ง ให้ใช้ .toHaveBeenCalledTimes(1)
อย่าลืม เพิ่ม jest.restoreAllMocks()
เข้าไปด้วย เพื่อให้มันเคลียค่าทุกครั้งในแต่ละการทดสอบ ถ้าไม่ได้ใส่เข้าไป jest จะนับจำนวนครั้งที่เรียกใช้งานเรื่อยๆ
import * as calculate from './calculate'
describe('spy self', () => {
afterEach(() => {
// restore the spy created with spyOn
jest.restoreAllMocks()
})
it('Should be called add when call doubleSum', () => {
const x = 2
const y = 2
const mathAddSpy = jest.spyOn(calculate, 'add')
calculate.doubleSum(x, y)
expect(mathAddSpy).toHaveBeenCalledTimes(1)
})
})
calculate.test.ts
Spy other files
หากเราต้องการที่จะ spy ในไฟล์อื่นๆ ก็สามารถทำได้ดังนี้
export const add = (x: number, y: number): number => x + y
math.ts
import { add } from '../math'
export const doubleSum = (x: number, y: number): number => {
const sum = add(x, y)
return x + y + sum
}
calculate.ts
import { doubleSum } from './calculate'
import * as math from './math'
describe('spy', () => {
afterEach(() => {
// restore the spy created with spyOn
jest.restoreAllMocks()
})
it('Should be called add when call doubleSum', () => {
const x = 2
const y = 2
const mathAddSpy = jest.spyOn(math, 'add')
doubleSum(x, y)
expect(mathAddSpy).toHaveBeenCalledTimes(1)
})
it('Should be return 9 when call doubleSum and send 2, 2', () => {
const x = 2
const y = 2
const actual = 9
// ใช้ spyOn ในการทำ Mock / Stub ได้
jest.spyOn(math, 'add').mockImplementation(() => 5)
const result = doubleSum(x, y)
expect(result).toBe(actual)
})
})
calculate.test.ts
Spy Library
เหมือนกันกับ mock function เราสามารถ spy ตัว library เพื่อตรวจสอบการทำงานได้ด้วยเช่นกัน
ตัวอย่าง
import _ from 'lodash'
export const getUserByUserName = (keyword: string) => {
var users = [
{ user: 'barney', birthday: '1980-01-01', age: 47 },
{ user: 'fred', birthday: '1990-01-01', age: 37 },
{ user: 'pebbles', birthday: '2000-01-01', age: 27 }
]
const index = _.findIndex(users, (o) => {
return o.user == keyword
})
return users[index]
}
user.test.ts
import _ from 'lodash'
import { getUserByUserName } from './user'
describe('Spy library', () => {
it('Should be called from findIndex with spy', () => {
const keyword = 'barney'
const findIndexSpy = jest.spyOn(_, 'findIndex').mockReturnValue(2)
getUserByUserName(keyword)
expect(findIndexSpy).toHaveBeenCalled()
})
it('Should be return user info from keyword with spy', () => {
const keyword = 'barney'
jest.spyOn(_, 'findIndex').mockReturnValue(2)
const actual = getUserByUserName(keyword)
// expect(findIndexSpy).toHaveBeenCalled()
expect(actual).toMatchObject({
user: 'pebbles',
birthday: '2000-01-01',
age: 27
})
})
})
user.test.ts
อันนี้เป็นตัวอย่างง่ายๆ ในการใช้งาน spy
ของ jest หากมีการใช้งานอื่นๆ เพิ่มเติม ก็สามารถเข้าไปดูใน document ของ jest ได้เหมือนเดิม