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 ขึ้นมาครับ และใส่โค้ดดังนี้ครับ

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 ขึ้นมาครับ แล้วใส่โค้ดดังนี้ครับ

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 ขึ้นมาครับ

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 เราจะปรับเป็นแบบนี้ครับ

package.json
  "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 เช่นกัน

จริง ๆ พระเอกคือบรรทัดนี้เลยครับ

redis.helper.test.js
jest.mock('redis', () => jest.requireActual('redis-mock'))

ก็คือใช้ jest.mock เพื่อ mock redis โดยใช้ redis-mock ช่วยจัดการ

หากบทความนี้มีส่วนไหนผิดพลาดประการใด ก็ขออภัยมา ณ ที่นี้ด้วยเน้อครับ หรือหากมีคำถามสงสัยตรงส่วนไหน อาจจะทักแชทส่วนตัวมาก็ได้ครับ เดี๋ยวถ้ามีกล่อง comment น่าจะสะดวกขึ้น ตอนนี้ยังไม่ได้ทำไว้ครับ ^^

Github: https://github.com/jame3032002/redis-testing