简体   繁体   English

如何在自定义函数中模拟 Axios?

[英]How to mock Axios inside a custom function?

Question

How can I mock axios.get() when it is inside my own custom function?axios.get()在我自己的自定义函数中时,我如何模拟它?

I am completely lost at this point.在这一点上我完全迷失了。 Hope someone can see what I am doing wrong.希望有人能看到我做错了什么。

Details细节

I have the below getString() function which downloads the html from a website and returns a value > 0 if the string was found and -1 if string not found.我有下面的getString()函数,它从网站下载 html,如果找到字符串,则返回值> 0如果未找到字符串,则返回-1

Since getString() uses axios.get() to download the html, I would like to Jest mock this call.由于getString()使用axios.get()下载 html,我想 Jest 模拟这个调用。

This article is the closest I can find to my situation, but in his case, he mocks a standalone axios.request() , where mine axios.get() is inside my custom getString() . 这篇文章是我能找到的最接近我的情况的文章,但在他的情况下,他axios.request()了一个独立的axios.request() ,其中我的axios.get()位于我的自定义getString()

My attempt is this:我的尝试是这样的:

getString.test.js获取字符串.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包.json

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

I have done npm init -y && npm install --save-dev jest , but npm run test gives me我已经完成了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?

The simple PoC works from the docs .简单的 PoC 来自docs

index.js索引.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获取字符串.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;
  }
};

First verify if jest is within your dependencies, and if it's not - install it首先验证jest是否在您的依赖项中,如果不是 - 安装它

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

and then test your implementation by mocking axios rather than the implementation that you want to test.然后通过axios而不是您要测试的实现来测试您的实现。

And the rest of the getString could look something like this其余的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)
      })
    })
  })
})

Edit: in order to achieve 100% coverage you'll also have to test your implementation's transformResponse and in order to do that you can mock the implementation like this编辑:为了实现 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 工作示例

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM