許多開發人員在測試程式碼時面臨挑戰。如果沒有適當的測試,錯誤可能會溜走,導致用戶沮喪和昂貴的修復。
本文將向您展示如何在使用 Node.js 和 MongoDB 建構的非常簡單的範例中使用 Jest、Supertest 和 Puppeteer 有效應用單元、整合和端到端測試。
讀完本文,我希望您能夠清楚地了解如何在自己的專案中應用這些類型的測驗。
??請在此儲存庫中找到完整的範例。
在安裝依賴項之前,讓我先介紹一下我們的範例。這是一個非常簡單的範例,用戶可以打開註冊頁面,設定其註冊詳細信息,點擊註冊按鈕,並將其資訊儲存在資料庫中。
在此範例中,我們將使用以下套件:
npm install --save jest express mongoose validator npm install --save-dev jest puppeteer jest-puppeteer mongodb-memory-server supertest npm-run-all
大多數依賴項都很簡單,但以下是其中一些依賴項的說明:
很好,讓我們將其翻譯成程式碼。
為了執行單元測試而沒有不可預測的行為,您應該在每次測試之前重置模擬函數。您可以使用 beforeEach 掛鉤來實現此目的:
// setup.unit.js beforeEach(() => { jest.resetAllMocks(); jest.restoreAllMocks(); });
在本例中,我們要測試 validateInput 函數:
npm install --save jest express mongoose validator npm install --save-dev jest puppeteer jest-puppeteer mongodb-memory-server supertest npm-run-all
這是一個非常簡單的函數,用於驗證提供的輸入是否包含有效的電子郵件。這是它的單元測試:
// setup.unit.js beforeEach(() => { jest.resetAllMocks(); jest.restoreAllMocks(); });
await Expect(async () => {}).rejects:根據 Jest 文檔,這是期望被拒絕的 Promise 原因的方法。
讓我們測試另一個函數,檢查資料庫中是否有重複的電子郵件。實際上,這一點很有趣,因為我們必須處理資料庫,同時單元測試不應該處理外部系統。那我們該怎麼辦呢?好吧,我們應該使用 Mocks。
首先,看看我們需要測試的 emailShouldNotBeDuplicated 函數:
// register.controller.js const validator = require('validator'); const registerController = async (input) => { validateInput(input); ... }; const validateInput = (input) => { const { name, email, password } = input; const isValidName = !!name && validator.isLength(name, { max: 10, min: 1 }); if (!isValidName) throw new Error('Invalid name'); ... };
如您所見,此函數會向資料庫發送請求以檢查是否有其他使用者俱有相同的電子郵件地址。以下是我們如何模擬資料庫呼叫:
// __tests__/unit/register.test.js const { registerController } = require('../controllers/register.controller'); describe('RegisterController', () => { describe('validateInput', () => { it('should throw error if email is not an email', async () => { const input = { name: 'test', email: 'test', password: '12345678' }; await expect(async () => await registerController(input)).rejects.toThrow('Invalid email'); }); }); });
我們使用 jest.spyOn(object, methodName) 模擬(監視)資料庫 findOne 方法,該方法建立一個模擬函數並追蹤其呼叫。因此,我們可以使用 toHaveBeenNthCalledWith 來追蹤監視的 findOne 方法的呼叫次數和傳遞的參數。
在編寫整合測試之前,我們必須先配置我們的環境:
npm install --save jest express mongoose validator npm install --save-dev jest puppeteer jest-puppeteer mongodb-memory-server supertest npm-run-all
現在,我們已準備好執行整合測試。
讓我們測試整個伺服器端註冊過程——從發送註冊請求到將用戶詳細資訊儲存在資料庫中並重定向到成功頁面:
// setup.unit.js beforeEach(() => { jest.resetAllMocks(); jest.restoreAllMocks(); });
如您所見,registerController 函數整合了多個元件(函數),validateInput、emailShouldNotBeDuplicated 和 createUser 函數。
那麼,讓我們來寫整合測試:
// register.controller.js const validator = require('validator'); const registerController = async (input) => { validateInput(input); ... }; const validateInput = (input) => { const { name, email, password } = input; const isValidName = !!name && validator.isLength(name, { max: 10, min: 1 }); if (!isValidName) throw new Error('Invalid name'); ... };
讓我們開始我們的範例。
實際上,在我們的範例中,端到端測試的環境配置與整合測試類似。
在這種情況下,我們需要準確模擬真實的使用者註冊行為,從開啟註冊頁面,填寫詳細資料(姓名、電子郵件、密碼),點擊「註冊」按鈕,最後重新導向到成功頁面。看一下程式碼:
npm install --save jest express mongoose validator npm install --save-dev jest puppeteer jest-puppeteer mongodb-memory-server supertest npm-run-all
讓我們分解這段程式碼:
照片由 Nathan Dumlao 在 Unsplash 上拍攝
此時,您可能想知道當每個測試類型都有自己的配置時如何同時執行所有測試類型。例如:
那麼,我們如何同時執行所有測試類型,同時確保每個測試類型都遵循其對應的配置?
要解決此問題,請按照以下步驟操作:
1. 讓我們建立三個不同的設定文件,jest.unit.config.js:
// setup.unit.js beforeEach(() => { jest.resetAllMocks(); jest.restoreAllMocks(); });
jest.integration.config.js:
// register.controller.js const validator = require('validator'); const registerController = async (input) => { validateInput(input); ... }; const validateInput = (input) => { const { name, email, password } = input; const isValidName = !!name && validator.isLength(name, { max: 10, min: 1 }); if (!isValidName) throw new Error('Invalid name'); ... };
jest.e2e.config.js:
// __tests__/unit/register.test.js const { registerController } = require('../controllers/register.controller'); describe('RegisterController', () => { describe('validateInput', () => { it('should throw error if email is not an email', async () => { const input = { name: 'test', email: 'test', password: '12345678' }; await expect(async () => await registerController(input)).rejects.toThrow('Invalid email'); }); }); });
2. 接下來,更新 package.json 檔案中的 npm 腳本,如下所示:
// register.controller.js const { User } = require('../models/user'); const registerController = async (input) => { ... await emailShouldNotBeDuplicated(input.email); ... }; const emailShouldNotBeDuplicated = async (email) => { const anotherUser = await User.findOne({ email }); if (anotherUser) throw new Error('Duplicated email'); };
--config:指定 Jest 設定檔的路徑。
npm-run-all --parallel:允許並行運行所有測試。
3. 然後,建立三個名為 setup.unit.js、setup.integration.js 和 setup.e2e.js 的安裝文件,其中包含前面部分中使用的必要安裝程式碼。
4. 最後,透過執行此命令 npm run test 來執行所有測試。該命令將根據各自的配置並行執行所有單元、整合和端到端測試。
在本文中,我們探討了單元、整合和端到端 (E2E) 測試,強調它們對於建立可靠應用程式的重要性。我們在 Node.js 和 MongoDB 的簡單使用者註冊範例中示範如何使用 Jest、Supertest 和 Puppeteer 來實作這些測試方法。
事實上,可靠的測試策略不僅可以提高程式碼質量,還可以增強開發人員的信心並提高用戶滿意度。
我希望這篇文章為您提供了有用的見解,您可以將其應用到您自己的專案中。測試愉快!
如果您發現本文有用,請查看以下文章:
非常感謝您一直陪伴我到現在。我希望您喜歡閱讀這篇文章。
以上是使用 Jest 的一個範例中的單元、整合和 ETesting的詳細內容。更多資訊請關注PHP中文網其他相關文章!