Có thể là một thách thức để kiểm tra các mô hình Mongoose vì bạn cần phải viết các bài kiểm tra không can thiệp vào cơ sở dữ liệu thực tế của bạn. Gói máy chủ bộ nhớ MongoDB cung cấp một giải pháp đơn giản. Nó cho phép bạn lưu trữ dữ liệu thử nghiệm của mình trong bộ nhớ ứng dụng.
Trong hướng dẫn này, bạn sẽ tạo một mô hình Mongoose đơn giản và viết các bài kiểm tra bằng cách sử dụng Jest và máy chủ bộ nhớ MongoDB.
Máy chủ bộ nhớ MongoDB là gì?
Điều cuối cùng bạn muốn là lưu dữ liệu giả mạo trong cơ sở dữ liệu thực của bạn, điều này có thể xảy ra nếu bạn kết nối với nó trong quá trình thử nghiệm. Thay vào đó, bạn có thể chọn sử dụng một phiên bản MongoDB cục bộ riêng biệt để lưu trữ dữ liệu của mình. Mặc dù điều này hoạt động nhưng sẽ không khả thi nếu các thử nghiệm của bạn chạy trên đám mây. Hơn nữa, việc kết nối và truy vấn cơ sở dữ liệu thực trong mỗi lần kiểm tra có thể tốn kém.
Tuy nhiên, máy chủ bộ nhớ MongoDB quay một máy chủ MongoDB thực và cho phép bạn lưu trữ dữ liệu thử nghiệm trong bộ nhớ. Điều này làm cho nó nhanh hơn so với sử dụng cơ sở dữ liệu MongoDB cục bộ vì dữ liệu không được ghi trên đĩa vật lý.
Tạo mô hình Mongoose
Các mô hình Mongoose cung cấp một giao diện để giao tiếp với cơ sở dữ liệu MongoDB. Để tạo chúng, bạn cần biên dịch chúng từ lược đồ Mongoose, lược đồ này xác định mô hình dữ liệu MongoDB của bạn. Hướng dẫn này sẽ sử dụng một lược đồ cho một tài liệu việc cần làm. Nó sẽ chứa tiêu đề và các trường đã hoàn thành.
Chạy lệnh sau trong terminal để tạo một thư mục mới và điều hướng đến nó.
mkdir mongoose-model-test
cd mongoose-model-test
Khởi tạo npm bằng lệnh sau:
npm init -y
Các -y cờ hướng dẫn npm tạo tệp package.json với các giá trị mặc định.
Thực thi lệnh này để cài đặt cầy mangut bưu kiện:
npm install mongoose
Tạo một tệp mới có tên todo.model.js và xác định lược đồ việc cần làm:
const mongoose = require("mongoose")
const { Schema } = mongoose
const TodoSchema = new Schema({
item: {
type: String,
required: true
},
compeleted: {
type: Boolean,
required: true
}
})
Ở cuối tệp này, hãy tạo và xuất mô hình việc cần làm:
module.exports = mongoose.model("Todo", TodoSchema)
Lập kế hoạch kiểm tra
Khi viết bài kiểm tra, bạn muốn lập kế hoạch trước những gì bạn sẽ kiểm tra. Điều này đảm bảo bạn đang thử nghiệm tất cả các chức năng của mô hình của bạn.
Từ mô hình Mongoose mà chúng tôi đã tạo, việc cần làm phải chứa một mục kiểu String và một trường hoàn chỉnh kiểu Boolean. Cả hai trường này đều là bắt buộc. Điều này có nghĩa là, tối thiểu, thử nghiệm của chúng tôi phải đảm bảo:
- Các mục hợp lệ được lưu thành công trong cơ sở dữ liệu.
- Các mục không có trường bắt buộc sẽ không được lưu.
- Các mục có trường thuộc loại không hợp lệ sẽ không được lưu.
Chúng tôi sẽ viết các bài kiểm tra này trong một khối kiểm tra vì chúng có liên quan với nhau. Trong Jest, bạn xác định khối kiểm tra này bằng cách sử dụng mô tả hàm số. Ví dụ:
describe('Todo Model Test', () => {
}
Thiết lập cơ sở dữ liệu
Để thiết lập máy chủ bộ nhớ MongoDB, bạn sẽ tạo một phiên bản máy chủ bộ nhớ Mongo mới và kết nối với Mongoose. Bạn cũng sẽ tạo các hàm chịu trách nhiệm loại bỏ tất cả các bộ sưu tập trong cơ sở dữ liệu và ngắt kết nối khỏi phiên bản máy chủ bộ nhớ Mongo.
Chạy lệnh sau để cài đặt mongodb-memory-server.
npm install mongodb-memory-server
Tạo một tệp mới có tên setuptestdb.js và nhập mongoose và mongodb-memory-server.
const mongoose = require("mongoose");
const { MongoMemoryServer } = require("mongodb-memory-server");
Tiếp theo, tạo một hàm connectDB (). Hàm này tạo một phiên bản máy chủ bộ nhớ Mongo mới và kết nối với Mongoose. Bạn sẽ chạy nó trước tất cả các bài kiểm tra để kết nối với cơ sở dữ liệu kiểm tra.
let mongo = null;
const connectDB = async () => {
mongo = await MongoMemoryServer.create();
const uri = mongo.getUri();
await mongoose.connect(uri, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
};
Tạo một hàm dropDB () bằng cách thêm đoạn mã sau. Hàm này xóa cơ sở dữ liệu, đóng kết nối Mongoose và dừng phiên bản máy chủ bộ nhớ Mongo. Bạn sẽ chạy chức năng này sau khi tất cả các thử nghiệm đã chạy xong.
const dropDB = async () => {
if (mongo) {
await mongoose.connection.dropDatabase();
await mongoose.connection.close();
await mongo.stop();
}
};
Hàm cuối cùng bạn sẽ tạo được gọi là dropCollections (). Nó loại bỏ tất cả các bộ sưu tập Mongoose đã tạo. Bạn sẽ chạy nó sau mỗi lần kiểm tra.
const dropCollections = async () => {
if (mongo) {
const collections = await mongoose.connection.db.collections();
for (let collection of collections) {
await collection.remove();
}
}
};
Cuối cùng, xuất các hàm conenctDB (), dropDB () và dropCollections ().
module.exports = { connectDB, dropDB, dropCollections}
Viết bài kiểm tra
Như đã đề cập, bạn sẽ sử dụng Jest để viết các bài kiểm tra. Chạy lệnh sau để cài đặt jest.
npm install jest
bên trong package.json tập tin, cấu hình jest. Thay thế khối “tập lệnh” hiện có của bạn bằng khối sau:
"scripts": {
"test": "jest --runInBand --detectOpenHandles"
},
"jest": {
"testEnvironment": "node"
},
Tạo một tệp mới có tên todo.model.test.js và nhập thư viện mongoose, mô hình todo và các hàm conenctDB (), dropDB () và dropCollections ():
const mongoose = require("mongoose");
const { connectDB, dropDB, dropCollections } = require("./setupdb");
const Todo = require("./todo.model");
Bạn cần chạy chức năng connectDB () trước khi chạy tất cả các thử nghiệm. Với Jest, bạn có thể sử dụng phương thức beforeAll ().
Bạn cũng cần chạy các chức năng dọn dẹp. Sau mỗi lần kiểm tra, hãy chạy hàm dropCollections () và hàm dropDB () sau tất cả các lần kiểm tra. Bạn không cần phải làm điều này theo cách thủ công và có thể sử dụng các phương thức afterEach () và afterAll () từ Jest.
Thêm mã sau vào tệp todo.model.test.js để thiết lập và dọn dẹp cơ sở dữ liệu.
beforeAll(async () => {
await connectDB();
});
afterAll(async () => {
await dropDB();
});
afterEach(async () => {
await dropCollections();
});
Bây giờ bạn đã sẵn sàng để tạo các bài kiểm tra.
Thử nghiệm đầu tiên sẽ kiểm tra xem mục việc cần làm đã được chèn thành công vào cơ sở dữ liệu hay chưa. Nó sẽ kiểm tra xem Id đối tượng có trong đối tượng được tạo hay không và dữ liệu trong đó có khớp với dữ liệu bạn đã gửi đến cơ sở dữ liệu hay không.
Tạo một khối mô tả và thêm mã sau.
describe("Todo Model", () => {
it("should create a todo item successfully", async () => {
let validTodo = {
item: "Do the dishes",
completed: false,
};
const newTodo = await Todo(validTodo);
await newTodo.save();
expect(newTodo._id).toBeDefined();
expect(newTodo.item).toBe(validTodo.item);
expect(newTodo.completed).toBe(validTodo.completed);
});
});
Điều này tạo ra một tài liệu mới trong cơ sở dữ liệu có chứa dữ liệu trong biến validTodo. Đối tượng được trả về sau đó được xác thực so với các giá trị mong đợi. Để kiểm tra này vượt qua, giá trị trả về phải có ID đối tượng. Ngoài ra, các giá trị trong mục và các trường đã hoàn thành phải khớp với các giá trị trong đối tượng validTodo.
Ngoài việc kiểm tra trường hợp sử dụng thông thường, bạn cũng cần phải kiểm tra trường hợp sử dụng không thành công. Từ các thử nghiệm mà chúng tôi đã lên kế hoạch, bạn cần kiểm tra mô hình mongoose với một đối tượng todo, với một trường bắt buộc bị thiếu và một trường có kiểu không chính xác.
Thêm thử nghiệm thứ hai vào cùng một khối mô tả, như sau:
it("should fail for todo item without required fields", async () => {
let invalidTodo = {
item: "Do the dishes",
};
try {
const newTodo = new Todo(invalidTodo);
await newTodo.save();
} catch (error) {
expect(error).toBeInstanceOf(mongoose.Error.ValidationError);
expect(error.errors.completed).toBeDefined();
}
});
Mô hình mongoose Todo mong đợi cả trường mục và trường đã hoàn thành. Nó sẽ xuất hiện một lỗi nếu bạn cố gắng lưu một việc cần làm mà không có một trong các trường này. Kiểm tra này sử dụng khối try… catch để bắt lỗi được đưa ra. Kiểm tra mong đợi các lỗi là lỗi xác thực mongoose và xuất phát từ trường đã hoàn thành bị thiếu.
Để kiểm tra xem mô hình có gặp lỗi hay không nếu bạn sử dụng các giá trị không đúng loại, hãy thêm mã sau vào khối mô tả.
it("should fail for todo item with fields of wrong type", async () => {
let invalidTodo = {
item: "Do the dishes",
completed: "False"
};
try {
const newTodo = new Todo(invalidTodo);
await newTodo.save();
} catch (error) {
expect(error).toBeInstanceOf(mongoose.Error.ValidationError);
expect(error.errors.completed).toBeDefined();
}
});
Lưu ý giá trị của trường đã hoàn thành là một chuỗi thay vì boolean. Việc kiểm tra mong đợi một lỗi xác thực được ném ra vì mô hình mong đợi một giá trị boolean.
MongoMemoryServer và Jest Tạo nên một đội tuyệt vời
Gói npm mongo-memory-server cung cấp một giải pháp dễ dàng để kiểm tra các mô hình Mongoose. Bạn có thể lưu trữ dữ liệu giả trong bộ nhớ mà không cần chạm vào cơ sở dữ liệu của ứng dụng.
Bạn có thể sử dụng MongoMemoryServer với Jest để viết các bài kiểm tra cho các mô hình Mongoose. Lưu ý rằng nó không bao gồm tất cả các bài kiểm tra có thể có mà bạn có thể viết cho các mô hình của mình. Những thử nghiệm đó sẽ phụ thuộc vào lược đồ của bạn.