如何在同一端点模拟两个 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 方法接收两个参数,reqres。如果您在测试中调用 read 时不提供这些对象,它将中断,因为您正在调用 res 对象的方法。

调用该方法的最简单方法是创建伪造的 reqres 对象并使用它们调用 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 方法不使用请求的任何 属性。