【问题标题】:How to mock Axios inside a custom function?如何在自定义函数中模拟 Axios?
【发布时间】:2021-02-22 07:33:13
【问题描述】:

问题

axios.get() 在我自己的自定义函数中时,如何模拟它?

此时我完全迷失了。希望有人能看到我做错了什么。

详情

我有下面的 getString() 函数,它从网站下载 html,如果找到字符串,则返回值 > 0,如果找不到字符串,则返回 -1

由于getString() 使用axios.get() 下载html,我想开玩笑地模拟这个调用。

This article 是我能找到的最接近我的情况,但在他的情况下,他模拟了一个独立的axios.request(),其中我的axios.get() 在我的自定义getString() 中。

我的尝试是这样的:

getString.test.js

const axios = require('axios');
const getString = require('./getString');

jest.mock('./getString', () => {
  return {
    baseURL: 'localhost',
    get: jest.fn().mockResolvedValue({
      data: 'xxx If you are the website administrator xxx'
    }),
  }
});

packages.json

{
  "name": "jest",
  "version": "1.0.0",
  "description": "",
  "main": "getString.js",
  "scripts": {
    "test": "jest"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

我已经完成了npm init -y && npm install --save-dev jest,但是npm run test 给了我

$ npm run test

> jest@1.0.0 test /home/mje/projects/jest
> jest

sh: jest: command not found
npm ERR! code ELIFECYCLE
npm ERR! syscall spawn
npm ERR! file sh
npm ERR! errno ENOENT
npm ERR! jest@1.0.0 test: `jest`
npm ERR! spawn ENOENT
npm ERR! 
npm ERR! Failed at the jest@1.0.0 test script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm WARN Local package.json exists, but node_modules missing, did you mean to install?

简单的 PoC 来自 the docs

index.js

const getString = require('./getString');

(async function(){
  'use strict'

  const isOk = await getString({
    url:          'http://localhost',
    string:       'If you are the website administrator',
    timeout:      1000,
    maxRedirects: 0
  });

  console.log(isOk);
})();

getString.js

const axios = require('axios');
const qs = require('qs');

module.exports = async (options) => {
  options              = options || {};
  options.url          = options.url || {};
  options.string       = options.string || null;
  options.timeout      = options.timeout || 1000;
  options.maxRedirects = options.maxRedirects || 0;

  try {
    const response = await axios.get(options.url, {
      timeout: options.timeout,
      maxRedirects: options.maxRedirects,
      validateStatus: null,
      transformResponse: [function (data) {
        return data.search(options.string);
  }]
    });
    return await response.data;
  } catch (error) {
    return -1;
  }
};

【问题讨论】:

  • 你是否安装了 jest 作为依赖项?

标签: javascript node.js ecmascript-6 axios jestjs


【解决方案1】:

首先验证 jest 是否在您的依赖项中,如果不在 - 安装它

yarn add --dev jest || npm i -D jest

然后通过模拟 axios 而不是您要测试的实现来测试您的实现。

getString 的其余部分可能看起来像这样

const axios = require('axios');
const getString = require('./getString');

jest.mock('axios')

const mockResponseData = {
  hello: "world"
}

describe('getString', () => {
  describe('axios returning resolved promise', () => {
    beforeAll(() => {
      // returning transformed mock
      axios.get.mockResolvedValue({
        data: mockResponseData
      })
    })

    describe('called with arguments', () => {
      let result
      beforeAll(() => {
        result = getString({
          url: 'http://localhost',
          string: 'If you are the website administrator',
          timeout: 1000,
          maxRedirects: 0
        })
      })

      it('should call axios.get', async () => {
        await result
        expect(axios.get).toHaveBeenCalledWith(
          "http://localhost",
          {
            "maxRedirects": 0,
            "timeout": 1000,
            "transformResponse": [
              expect.any(Function)
            ],
            "validateStatus": null
          }
        )
      })

      it('should return the response.data', async () => {
        expect(await result).toEqual(mockResponseData)
      })
    })
  })

  describe('axios returning rejected promise', () => {
    beforeAll(() => {
      // returning transformed mock
      axios.get.mockRejectedValue({
        data: mockResponseData
      })
    })

    describe('called with arguments', () => {
      let result
      beforeAll(() => {
        result = getString({
          url: 'http://localhost',
          string: 'If you are the website administrator',
          timeout: 1000,
          maxRedirects: 0
        })
      })

      it('should return -1', async () => {
        expect(await result).toEqual(-1)
      })
    })
  })
})

编辑:为了实现 100% 的覆盖率,您还必须测试您的实现的 transformResponse,为了做到这一点,您可以像这样模拟实现

// this is not tested
import mockResponseBody from './localMock.json';

axios.get.mockImplementation((url, { transformResponse }) =>
    Promise.resolve({
        data: transformResponse.reduce((acc, fn) => fn(acc), mockResponseData)
    })
)


working example

【讨论】:

  • 如何运行测试? npm run test?当我在你的 repl.it 上这样做时,它会显示 Error: no test specified,所以我想你以不同的方式运行它?
  • @SandraSchlichting on repl.it 只需按下上面的Run 按钮。在命令行中使用npm run test 应该使用默认配置
  • 很高兴为您提供帮助:)
  • @SandraSchlichting 因为在我的 repl.it 示例中,transformResponse 没有被考虑在内
  • 嗨 @Teneff 我看到你在玩笑话方面有很好的经验你能检查一下这个stackoverflow.com/questions/64770117/…
猜你喜欢
  • 2020-10-24
  • 2011-08-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-30
  • 2021-02-08
  • 2019-07-22
相关资源
最近更新 更多