如何在同一端点模拟两个 axios 调用
How to mock two axios call in same endpoint
示例:
在我的测试中,我需要模拟对外部 api 的两次调用。
我不能嘲笑第二个电话。使用库 'axios-mock-adapter' 和 ava 我只能模拟第一个调用。
const read = async (req, res) => {
try {
const responseOne = await axios({
method: 'get',
url: 'https://api.example.com/search/repositories',
params: {
q: 'example',
},
})
const resultOne = responseOne.data
if (resultOne) {
let aux = []
const itemsOne = resultOne.items.slice(0, 10)
return Promise.all(
itemsOne.map((p, indexOne) => {
aux = [...aux, { id: p.id, name: p.name, arr: [] }]
return axios({
headers: { Authorization: `Bearer ${SECRET_KEY}` },
method: 'get',
url: 'https://api.example2.com/search/things',
params: { q: p.name },
})
.then(responseTwo =>
responseTwo.data.array.map(i => {
aux[indexOne].arr.push({
id: i.id,
created_at: i.created_at,
text: i.text,
})
})
)
.catch(err => res.status(500).json(err))
})
)
.then(() => res.json({ result: aux }))
.catch(err => res.status(500).json(err))
} else res.status(404).json({ message: 'Example not found' })
} catch (err) {
res.status(500).json(err)
}
}
测试
这是我的测试read.test.js。
现在我正在处理 'ava' 和 'axios-mock-adapter' 库。但是第二个 axios 调用在模拟中不起作用。
import axios from 'axios'
import MockAdapter from 'axios-mock-adapter'
import test from 'ava'
import read from '../read'
var mock = new MockAdapter(axios)
test('GET - /examples', async t => {
mock
.onGet('https://api.example.com/search/repositories, {
params: {
q: 'example',
},
})
.reply(200, {
total_count: 2,
incomplete_results: false,
items: [
{
id: 555,
name: 'exampleOne',
},
{
id: 666,
name: 'exampleTwo',
},
],
})
.onGet('https://api.example2.com/search/things', {
params: { q: 'name' },
headers: { Authorization: `Bearer ${SECRET_KEY}` },
})
.reply(200, {
statuses: [
{
id: 123,
created_at: 'Thu Feb 27 22:54:02 +0000 2020',
text: 'Example one.',
},
{
id: 456,
created_at: 'Wed Feb 26 13:40:20 +0000 2020',
text: 'Example Two',
},
],
})
try {
const res = await read()
t.assert(res.result[0].id.test(555))
} catch (err) {
console.log(`ERROR::: ${err}`)
}
第二个请求的模拟问题是您将其配置为仅在使用参数 { q: 'name' }
请求端点时才响应。如果您想对 https://api.example2.com/search/things
的所有请求都使用相同的数据进行响应,则删除该参数属性就足够了:
.onGet('https://api.example2.com/search/things', {
headers: { Authorization: `Bearer ${SECRET_KEY}` },
})
.reply(200, {
statuses: [
{
id: 123,
created_at: 'Thu Feb 27 22:54:02 +0000 2020',
text: 'Example one.',
},
{
id: 456,
created_at: 'Wed Feb 26 13:40:20 +0000 2020',
text: 'Example Two',
},
],
})
您的测试中还存在其他问题。在模拟响应中,您正在 属性 statuses
中传递数据,但在您的实际代码中,您正在迭代 array
属性.
此外,read
方法接收两个参数,req
和 res
。如果您在测试中调用 read
时不提供这些对象,它将中断,因为您正在调用 res
对象的方法。
调用该方法的最简单方法是创建伪造的 req
和 res
对象并使用它们调用 read
方法。为了简单起见,我将在 sinon spies:
的帮助下创建模拟
test('GET - /examples', async t => {
mock
.onGet('https://api.example.com/search/repositories, {
params: {
q: 'example',
},
})
.reply(200, {
total_count: 2,
incomplete_results: false,
items: [
{
id: 555,
name: 'exampleOne',
},
{
id: 666,
name: 'exampleTwo',
},
],
})
.onGet('https://api.example2.com/search/things', {
headers: { Authorization: `Bearer ${SECRET_KEY}` },
})
.reply(200, {
array: [
{
id: 123,
created_at: 'Thu Feb 27 22:54:02 +0000 2020',
text: 'Example one.',
},
{
id: 456,
created_at: 'Wed Feb 26 13:40:20 +0000 2020',
text: 'Example Two',
},
],
})
const res = {
status: sinon.stub().returnsThis(),
json: sinon.stub().returnsThis(),
};
try {
await read({}, res);
const data = res.json.firstCall.args[0];
t.is(data.result[0].id, 555)
} catch (err) {
console.log(`ERROR::: ${err}`)
}
});
请注意,我通过传递一个空对象来模拟请求对象,因为 read
方法不使用请求的任何 属性。
示例:
在我的测试中,我需要模拟对外部 api 的两次调用。 我不能嘲笑第二个电话。使用库 'axios-mock-adapter' 和 ava 我只能模拟第一个调用。
const read = async (req, res) => {
try {
const responseOne = await axios({
method: 'get',
url: 'https://api.example.com/search/repositories',
params: {
q: 'example',
},
})
const resultOne = responseOne.data
if (resultOne) {
let aux = []
const itemsOne = resultOne.items.slice(0, 10)
return Promise.all(
itemsOne.map((p, indexOne) => {
aux = [...aux, { id: p.id, name: p.name, arr: [] }]
return axios({
headers: { Authorization: `Bearer ${SECRET_KEY}` },
method: 'get',
url: 'https://api.example2.com/search/things',
params: { q: p.name },
})
.then(responseTwo =>
responseTwo.data.array.map(i => {
aux[indexOne].arr.push({
id: i.id,
created_at: i.created_at,
text: i.text,
})
})
)
.catch(err => res.status(500).json(err))
})
)
.then(() => res.json({ result: aux }))
.catch(err => res.status(500).json(err))
} else res.status(404).json({ message: 'Example not found' })
} catch (err) {
res.status(500).json(err)
}
}
测试
这是我的测试read.test.js。 现在我正在处理 'ava' 和 'axios-mock-adapter' 库。但是第二个 axios 调用在模拟中不起作用。
import axios from 'axios'
import MockAdapter from 'axios-mock-adapter'
import test from 'ava'
import read from '../read'
var mock = new MockAdapter(axios)
test('GET - /examples', async t => {
mock
.onGet('https://api.example.com/search/repositories, {
params: {
q: 'example',
},
})
.reply(200, {
total_count: 2,
incomplete_results: false,
items: [
{
id: 555,
name: 'exampleOne',
},
{
id: 666,
name: 'exampleTwo',
},
],
})
.onGet('https://api.example2.com/search/things', {
params: { q: 'name' },
headers: { Authorization: `Bearer ${SECRET_KEY}` },
})
.reply(200, {
statuses: [
{
id: 123,
created_at: 'Thu Feb 27 22:54:02 +0000 2020',
text: 'Example one.',
},
{
id: 456,
created_at: 'Wed Feb 26 13:40:20 +0000 2020',
text: 'Example Two',
},
],
})
try {
const res = await read()
t.assert(res.result[0].id.test(555))
} catch (err) {
console.log(`ERROR::: ${err}`)
}
第二个请求的模拟问题是您将其配置为仅在使用参数 { q: 'name' }
请求端点时才响应。如果您想对 https://api.example2.com/search/things
的所有请求都使用相同的数据进行响应,则删除该参数属性就足够了:
.onGet('https://api.example2.com/search/things', {
headers: { Authorization: `Bearer ${SECRET_KEY}` },
})
.reply(200, {
statuses: [
{
id: 123,
created_at: 'Thu Feb 27 22:54:02 +0000 2020',
text: 'Example one.',
},
{
id: 456,
created_at: 'Wed Feb 26 13:40:20 +0000 2020',
text: 'Example Two',
},
],
})
您的测试中还存在其他问题。在模拟响应中,您正在 属性 statuses
中传递数据,但在您的实际代码中,您正在迭代 array
属性.
此外,read
方法接收两个参数,req
和 res
。如果您在测试中调用 read
时不提供这些对象,它将中断,因为您正在调用 res
对象的方法。
调用该方法的最简单方法是创建伪造的 req
和 res
对象并使用它们调用 read
方法。为了简单起见,我将在 sinon spies:
test('GET - /examples', async t => {
mock
.onGet('https://api.example.com/search/repositories, {
params: {
q: 'example',
},
})
.reply(200, {
total_count: 2,
incomplete_results: false,
items: [
{
id: 555,
name: 'exampleOne',
},
{
id: 666,
name: 'exampleTwo',
},
],
})
.onGet('https://api.example2.com/search/things', {
headers: { Authorization: `Bearer ${SECRET_KEY}` },
})
.reply(200, {
array: [
{
id: 123,
created_at: 'Thu Feb 27 22:54:02 +0000 2020',
text: 'Example one.',
},
{
id: 456,
created_at: 'Wed Feb 26 13:40:20 +0000 2020',
text: 'Example Two',
},
],
})
const res = {
status: sinon.stub().returnsThis(),
json: sinon.stub().returnsThis(),
};
try {
await read({}, res);
const data = res.json.firstCall.args[0];
t.is(data.result[0].id, 555)
} catch (err) {
console.log(`ERROR::: ${err}`)
}
});
请注意,我通过传递一个空对象来模拟请求对象,因为 read
方法不使用请求的任何 属性。