簡體   English   中英

如何在測試下一頁 api 時開玩笑地模擬 mongodb 客戶端?

[英]How to mock mongodb client when testing Nexts page api with jest?

我想用玩笑測試下一頁 api 文件,雖然目前測試運行良好,但我遇到了一些問題

  1. 每個頁面 API 發出的 POST 請求實際上都是在向 mongo 數據庫發送數據,即使我正在運行測試; 這是不可取的,因為當我測試此類 POST 請求時,我不希望測試數據在數據庫中
  2. 在某些情況下,我想模擬 mongo 連接失敗,以測試 500 狀態錯誤響應,但我不知道該怎么做

如何模擬 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM