🌞

Mock API bằng Mirage JS

Sửa bài viết này

Tại sao bạn cần giả lập (mock) API

FE sẽ ko phải đợi đến khi BE làm xong API mới có thể bắt đầu integrate, nếu bạn có thể mock những API sẽ được trả về dựa trên contract đã thống nhất, thì gần như là không còn quá nhiều việc phải làm khi API làm xong.

Làm như thế nào

Để mock API, kể thể dùng nhiều cách như JSON Server, mountebank, hôm nay mình hướng dẫn dùng Mirage mình mới biết, kết hợp với Vue nhé, React cũng tương tự thôi.

  1. Cài đặt vào devDependencies
npm i miragejs -D
  1. Mình chọn tổ chức thư mục theo kiểu này, bạn có thể để nó ở chỗ khác thì tùy ý
/
├── public
├── src
│   ├── api
│   │   └── mock
│   │       ├── fixtures
│   │       │   └── get-tasks.js
│   │       └── index.js
│   └── main.js
├── package.json
└── package-lock.json
  1. Tạo mock server
// api/mock/index.js
import { Server } from 'miragejs';

export default function ({ environment = 'development' } = {}) {
  return new Server({
    environment,
    routes() {
      // chút thêm routes ở đây
    },
  });
}
  1. Mở file dùng để bootstrap app của chúng ta, nếu dùng Vue nó sẽ là src/main.js (src/index.js nếu bạn dùng với React)
import createServer from './api/mock';

// chỉ tạo fake server trong lúc chạy dev mode
if (process.env.NODE_ENV === 'development') {
    createServer();
}

Ví dụ bạn gọi API trong code như thế này

await axios.get('/api/tasks');

Chúng ta sẽ cập nhập lại file api/mock/index.js, bổ sung route /api/tasks cho mock server

// api/mock/index.js

export default function ({ environment = 'development' } = {}) {
    // ...
    routes() {
      this.get('/api/tasks', () => ({
        tasks: [
          { id: 1, text: "Feed the cat" },
          { id: 2, text: "Wash the dishes" },
          //...
        ],
      }))
    },
  });
}

Tương tự để mock các HTTP method khác

this.get('/tasks', (schema, request) => { ... });
this.post('/tasks', (schema, request) => { ... });
this.patch('/tasks/:id', (schema, request) => { ... });
this.put('/tasks/:id', (schema, request) => { ... });
this.del('/tasks/:id', (schema, request) => { ... });
this.options('/tasks', (schema, request) => { ... });

Nếu mọi thứ êm đẹp bạn sẽ được thông báo trên cửa sổ console

Screenshot of a Mirage response in the console showing data for two task objects with IDs 1 and 2.

Thêm nội dung động

Bạn có thể dùng fakerjs để chèn thêm dữ liệu một cách ngẫu nhiên.

Để có dữ liệu init cho fake server, chúng ta sẽ sử dụng seeds()

export default function ({ environment = 'development' } = {}) {
    seeds(server) {
        server.db.loadData({
            tasks: [
                { id: 1, text: "Feed the cat" },
                { id: 2, text: "Wash the dishes" },
            ],
        })
    },
    routes() {
        this.get('/api/tasks', (schema) => {
            return schema.db.tasks;
        }),
        this.post('/api/tasks', (schema, request) => {
          // nhận data được gửi từ post
          const task = JSON.parse(request.requestBody).data;
          return schema.db.tasks.insert(task);
        })
        ...
    },
  });
}

Thêm route động

Route động là gì, ví dụ như bạn dùng phương thức delete hay update bằng một route như thế này

DELETE: /api/tasks/8lVzv5lv2n6Mu912x19UdKDC08
PUT: /api/tasks/8lVzv5lv2n6Mu912x19UdKDC08
// api/mock/index.js
...
this.delete('/api/tasks/:id', (schema, request) => {
  	// id từ url
    const id = request.params.id;
    return schema.db.tasks.remove(id);
})
...

Nếu bạn để ý, tất cả đều bắt đầu bằng api, namespace sinh ra là để phục vụ đối tượng lười biếng như chúng ta

routes() {
    // bọn dưới sẽ bắt đầu bằng /api hết
    this.namespace = '/api';

    this.get('/tasks', () => { ... })
    this.delete('/tasks/:id', () => { ... })
    this.post('/tasks', () => { ... })
}

Giả lập những route chỉ định

Nếu như bạn đã có một số API, một số BE đang implement, tất nhiên chúng ta chỉ mock những API chưa làm, còn cái nào làm rồi thì cứ xài cái thật luôn

routes() {
    // chỉ giả lập GET /task
    this.get('/task', () => { ... });
    
    // còn lại dùng hàng thật
    this.passthrough();
}

Nhưng đa phần API thật sẽ nằm đâu đó chứ không phải localhost:3000, thêm đoạn sau

routes() {
    // api thực nằm ở đây
    this.urlPrefix = 'https://devenv.ourapp.example';
    
    // chỉ giả lập GET /task
    this.get('/task', () => { ... });
    
    // còn lại dùng hàng thật
    this.passthrough();
}

Lúc này tất cả API đều sẽ gọi lên https://devenv.ourapp.example, duy chỉ gặp thằng https://devenv.ourapp.example/task`, mirage sẽ intercept và đưa hàng giả vào.

Kết

Sử dụng cũng được vài cái thư viện làm mock API, MirageJS là thằng mình thấy ưng nhất, không quá phức tạp, giải quyết được những vấn đề rất căn cơ của FE.

Mirage JS còn khá nhiều chiêu trò thú vị chờ bạn khám phá trên tài liệu chính thức của nó, nếu thấy hay đừng quên nhất like và contribute cho dự án trên Github

Happy coding 🎉🙌

Initializing...