[英]How to mock mongodb client when testing Nexts page api with jest?
我想用玩笑測試下一頁 api 文件,雖然目前測試運行良好,但我遇到了一些問題
如何模擬 mongoclient 連接,以便在連接成功后測試將項目插入數據庫,或者故意導致 mongo 客戶端連接錯誤?
newsletter.ts (PAGE API FILE)
import type { NextApiRequest, NextApiResponse } from 'next'
import { MongoClient } from 'mongodb'
async function connectDatabase() {
const client = await MongoClient.connect(<url>)
return client
}
async function insertDocument(client: MongoClient, document: { email: string }) {
const db = client.db()
await db.collection('newsletter').insertOne(document)
}
async function handler(req: NextApiRequest, res: NextApiResponse) {
const userEmail = JSON.parse(req.body).email
if (!userEmail || !userEmail.includes('@')) {
res.status(422).json({ message: 'Invalid email address' })
return
}
let client
try {
client = await connectDatabase()
} catch (error) {
res.status(500).json({ message: 'Connecting to the database failed!' })
return
}
try {
await insertDocument(client, { email: userEmail })
} catch(error) {
res.status(500).json({ message: 'Inserting data failed!' })
return
}
client.close()
res.status(201).json({ message: 'Signed up!' })
}
export default handler
這是測試代碼
newsletter.test.tsx (PAGE API TEST FILE)
import type { NextApiRequest, NextApiResponse } from 'next'
import {
createMocks as _createMocks,
Mocks,
RequestOptions,
ResponseOptions,
} from 'node-mocks-http'
import newsletter from '../../pages/api/newsletter'
const createMocks = _createMocks as (
reqOptions?: RequestOptions,
resOptions?: ResponseOptions
) => Mocks<NextApiRequest, NextApiResponse>
describe('Test responses for newsletter api', () => {
it('Should return status 201 with valid request body', async () => {
const { req, res } = createMocks({
method: 'POST',
body: JSON.stringify({
email: 'abc@email.com',
}),
})
await newsletter(req, res)
expect(res._getStatusCode()).toBe(201)
expect(JSON.parse(res._getData())) .toEqual(
expect.objectContaining({
message: 'Signed up!',
})
)
})
it('Should return status 422 with invalid req body', async () => {
const { req, res } = createMocks({
method: 'POST',
body: JSON.stringify({
email: 'abcemail.com',
}),
})
await newsletter(req, res)
expect(res._getStatusCode()).toBe(422)
expect(JSON.parse(res._getData())).toEqual(
expect.objectContaining({
message: 'Invalid email address',
})
)
})
})
找到了幫助我解決問題的答案
為了模擬 mongoclient,我只需要使用 jest.spyOn,並將用戶的所有其他函數鏈接到數據庫中。 這也阻止了對服務器的真正調用,並且不再發送測試數據。 為了模擬狀態 500 錯誤,我只是模擬了一個被拒絕的 promise。
代碼最終變成了這樣:
import type { NextApiRequest, NextApiResponse } from 'next'
import {
createMocks as _createMocks,
Mocks,
RequestOptions,
ResponseOptions,
} from 'node-mocks-http'
import { MongoClient } from 'mongodb'
import newsletter from '../../pages/api/newsletter'
const createMocks = _createMocks as (
reqOptions?: RequestOptions,
resOptions?: ResponseOptions
) => Mocks<NextApiRequest, NextApiResponse>
describe('Test responses for newsletter api', () => {
afterEach(() => {
jest.resetAllMocks()
})
it('Should return status 500 on failure to connect to database', async () => {
const { req, res } = createMocks({
method: 'POST',
//@ts-ignore
body: JSON.stringify({
email: 'abc@email.com',
}),
})
const connectSpy = jest.spyOn(MongoClient, 'connect').mockRejectedValueOnce(new Error)
await newsletter(req, res)
expect(connectSpy).toHaveBeenCalled()
expect(res._getStatusCode()).toBe(500)
})
it('Should return status 201 with valid request body', async () => {
const { req, res } = createMocks({
method: 'POST',
//@ts-ignore
body: JSON.stringify({
email: 'abc@email.com',
}),
})
const insertOne = jest.fn().mockResolvedValueOnce({ acknowleged: true })
const collection = jest.fn().mockReturnValueOnce({ insertOne })
const connectSpy = jest.spyOn(MongoClient, 'connect').mockResolvedValueOnce({ db: jest.fn().mockReturnValueOnce({ collection }), close: jest.fn() })
await newsletter(req, res)
expect(connectSpy).toHaveBeenCalled()
expect(res._getStatusCode()).toBe(201)
expect(JSON.parse(res._getData())) .toEqual(
expect.objectContaining({
message: 'Signed up!',
})
)
})
})
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.