- Published on
Redis testing
วันนี้เจมส์มีโอกาสได้ทดลองเขียน Test เกี่ยวกับ Mock Redis เลยอยากมาบันทึกไว้ เผื่อว่าจะมีประโยชน์กับคุณผู้อ่านทุกท่านครับ
สิ่งที่จะทำวันนี้คือสร้างไฟล์ server.js
ขึ้นมาอันนึงครับ แล้วก็สร้าง redis.helper.js
ขึ้นมาครับ โดยเราจะ Test ในส่วนของ setRedis กับ getRedis ที่สร้างขึ้นมาครับ
ซึ่ง server.js
เราจะแค่ให้ดูเฉย ๆ ว่า setRedis กับ getRedis ที่สร้างขึ้นมานั้นใช้งานได้จริง และ Redis ถูก set จริง
แต่เมื่อเรา run test มันจะไม่ไปยุ่งกับ redis ของจริง มันจะจำลอง redis ขึ้นมา ทำให้สะดวกในการ test มากขึ้นครับ
โดย Redis เราจะใช้จาก Docker เอาเน้อครับ
สิ่งที่อยากบันทึกไว้คือการ Mock Redis ให้เขียน Test ได้
สั่ง Run Redis จาก Docker
ขั้นแรกเดี๋ยวเราเริ่มจากสั่ง Run Redis จาก Docker ก่อนครับ โค้ดสำหรับสั่ง Run ดังนี้ครับ
docker run --name [ชื่อ container ที่ต้องการ] -p 6379:6379 -d redis
เช่น
docker run --name example-redis -p 6379:6379 -d redis
เมื่อเราใช้คำสั่ง docker ps
ดูจะพบว่ามี 1 Container ที่ Run อยู่
คราวนี้เราลองมาทดสอบ connect redis กันครับ เจมส์จะใช้ Extension ที่ติดตั้งเพิ่มใน VS Code มาลอง Connect Redis ดูครับ
โดย Search Extendsions ว่า redis
เจมส์ใช้อันที่เป็น Redis For VS Code อ่ะครับ ของ Dunn แล้วลอง connect ดูครับ
ในส่วนนี้เจมส์ติดตั้งมาเพื่อใช้ดูเฉย ๆ เน้อครับ คุณผู้อ่านจะติดตั้ง หรือไม่ติดตั้งก็แล้วแต่เลยครับ
สร้าง Project
ขั้นแรกคือเดี๋ยวเจมส์จะสร้าง Project ขึ้นมาก่อนครับชื่อ redis-testing
mkdir redis-testing
cd redis-testing
สร้าง package.json ด้วยคำสั่ง
npm init -y
เมื่อสร้างเรียบร้อยแล้ว จากนั้นเราจะ install redis ด้วยคำสั่ง
npm install --save redis@3.1.2
หมายเหตุ: เจมส์ทดสอบของ redis ของ version 4 แล้วเหมือนมีปัญหาตรงเทส ที่เราจะทำ เลยใช้เป็น version 3 ไปก่อนเน้อครับ เดี๋ยวถ้าหาวิธีแก้ได้แล้ว เดี๋ยวมาเขียนเพิ่มให้ครับ
จากนั้นเราจะสร้างไฟล์ server.js
ขึ้นมาครับ และใส่โค้ดดังนี้ครับ
const { setRedis, getRedis } = require('./redis.helper')
async function init() {
await setRedis({ key: 'kajame', value: 'hello world' })
const redisData = await getRedis({ key: 'kajame' })
console.log(redisData)
}
init()
จากนั้นให้เราสร้างไฟล์ redis.helper.js
ขึ้นมาครับ แล้วใส่โค้ดดังนี้ครับ
const { client } = require('./redis')
async function setRedis ({ key, value }) {
return new Promise((resolve, reject) => {
client.set(key, value, (err) => {
if(err) {
reject(err)
} else {
resolve()
}
})
})
}
function getRedis({ key }) {
return new Promise((resolve, reject) => {
client.get(key, (err, data) => {
if(err) {
reject(err)
} else {
resolve(data)
}
})
})
}
module.exports = {
setRedis,
getRedis
}
และสร้างไฟล์ redis.helper.test.js
ขึ้นมาครับ
jest.mock('redis', () => jest.requireActual('redis-mock'))
const { setRedis, getRedis } = require('./redis.helper')
describe('setRedis and getRedis', () => {
it('Should set and get data from redis', async () => {
const key = 'example'
const value = 'kajame'
await setRedis({ key, value })
const data = await getRedis({ key })
expect(data).toEqual(value)
})
})
ปรับไฟล์ package.json
อีกนิดครับ ในส่วนของ script เราจะปรับเป็นแบบนี้ครับ
"scripts": {
"test": "jest",
"dev": "node server.js"
},
หลังจากปรับทั้งหมดเรียบร้อยแล้ว ลองมาดูโค้ดกันก่อนดีกว่าครับว่าทำอะไรยังไงบ้าง
ไฟล์ redis.helper.js
เจมส์มี 2 ฟังก์ชันครับ คือ setRedis กับ getRedis ปรับจาก callback function เป็น Promise ฟังก์ชันเฉย ๆ ครับ
ไฟล์ server.js
เจมส์ไว้ใช้ดูว่า setRedis กับ getRedis สามารถใช้งานเป็นแบบ Promise ได้ ซึ่งถ้าหากเราลองสั่งด้วยคำสั่ง
node server
หรือ
npm run dev
จะพบว่ามันจะแสดงข้อความว่า hello world
เนื่องจากเรา setRedis ด้วยคีย์ kajame
โดยให้ value เป็นค่า hello world
จากนั้นให้ดึงค่าจาก redis โดยใช้คีย์ kajame
เข้าไปดึง ซึ่งเมื่อดึงมาแล้ว ให้ console.log ค่าที่ดึงออกมาได้ ซึ่งก็คือค่า hello world
ที่ set ไว้นั่นเองครับ
และเมื่อเราลอง connect redis ด้วย extension ของ VS Code โดยกำหนด IP address of the Redis server เป็น localhost
และกำหนด Port of the Redis server เป็น 6379
จะพบข้อมูล Redis ที่ถูก set 1 ข้อมูล ซึ่งก็คือ คีย์ kajame
และมีค่าเป็น hello world
นั่นแหละครับ
คราวนี้เมื่อลองสั่ง
npm run test
จะพบว่าผ่านหมด และเมื่อลอง refresh redis ที่ connect ก็จะไม่พบคีย์ใหม่เพิ่มขึ้นมา ทั้ง ๆ ที่ใน redis.helper.test.js
มีการ set และ get ค่า Redis เช่นกัน
จริง ๆ พระเอกคือบรรทัดนี้เลยครับ
jest.mock('redis', () => jest.requireActual('redis-mock'))
ก็คือใช้ jest.mock เพื่อ mock redis โดยใช้ redis-mock ช่วยจัดการ
หากบทความนี้มีส่วนไหนผิดพลาดประการใด ก็ขออภัยมา ณ ที่นี้ด้วยเน้อครับ หรือหากมีคำถามสงสัยตรงส่วนไหน อาจจะทักแชทส่วนตัวมาก็ได้ครับ เดี๋ยวถ้ามีกล่อง comment น่าจะสะดวกขึ้น ตอนนี้ยังไม่ได้ทำไว้ครับ ^^