模拟模块
模块可以分为两种模块:
- 第三方模块。
- 文件模块。
模拟第三方模块
假设现在项目中有如下的一个方法,现在需要对这个模块的方法进行一个测试,此时会涉及到一个问题,要测试这个模块就必然会涉及到使用axios发送真实的http请求,这个时候就要屏蔽这个真实的请求。
const axios = require('axios')
function getUsers() {
return new Promise(async (resolve) => {
try {
const res = await axios.get('/users.json')
resolve(res.data)
} catch (e) {
reject(e)
}
})
}
要解决这个问题,大概有两种方式:
- 模拟一个
getUsers函数,屏蔽内部的实现,但这种方式无法测试该方法内部的实现是否正确。 - 模拟
axios模块来屏蔽axios发送请求这个部分。
使用jest.mock来模拟axios这个模块:
- module.test.js
- users.json
const axios = require('axios')
const useData = require('./users.json')
// 模拟 axios 模块
jest.mock('axios')
test('Fetch user data', async () => {
const res = {
data: useData
}
axios.get.mockImplementation(() => Promise.resolve(res))
await expect(getUsers()).resolves.toEqual(useData)
})
[
{
"id": 1,
"name": "Tom"
},
{
"id": 2,
"name": "Nancy"
}
]
如上的的测试套件中,首先使用jest.mock方法模拟了axios这个模块。在测试用例里面,指定了axios.get方法的行为,之后对getUsers方法进行测试,在该方法里面使用到axios.get 方法,这个时候就会使用模拟的axios模块。
jest.mock也可传入第二个参数,该参数是一个工厂函数,可以指定模块的一些实现:
const axios = require('axios')
const useData = require('./users.json')
jest.mock('axios', () => {
const userData = require('./users.json')
const resp = {
data: userData
}
return {
get: jest.fn(() => Promise.resolve(resp))
}
})
test('Fetch user data', async () => {
await expect(getUsers()).resolves.toEqual(useData)
})
模拟本地模块
通过jest.mock,还可以模拟整个本地模块:
- module.test.js
- tools.js
const modulePath = './tools.js'
const { sum, sub, mul, div } = require(modulePath)
jest.mock(modulePath, () => {
const originalModule = jest.requireActual(modulePath)
return {
...originalModule,
sum: jest.fn(() => 100),
sub: jest.fn(() => 50)
}
})
test('test local module', () => {
expect(sum(1, 2)).toBe(100)
expect(sub(10, 2)).toBe(50)
expect(mul(6, 8)).toBe(48)
expect(div(100, 4)).toBe(25)
})
exports.sum = function (a, b) {
return a + b
}
exports.sub = function (a, b) {
return a - b
}
exports.mul = function (a, b) {
return a * b
}
exports.div = function (a, b) {
return a / b
}