使用 jest 时 axios mock 无法处理默认标头

Posted

技术标签:

【中文标题】使用 jest 时 axios mock 无法处理默认标头【英文标题】:axios mock can't handle default headers when using jest 【发布时间】:2019-07-13 01:46:57 【问题描述】:

我正在做一个测试,其中包括对端点的 axios 调用。我想模拟对端点的调用并返回一些自定义数据,这样我就不会在每次测试时都访问服务器。

这是它自己的 action.js 文件中的操作代码。

login (commit, user)  
  return new Promise((resolve, reject) => 
    axios.post('https://backendauth.free.beeceptor.com/api/login', user)
     .then(resp => 
       console.log('response here')
       console.log(resp)
       console.log(resp.data)
       const token = resp.data.success.token
       const user = resp.data.user
       localStorage.setItem('token', token)
       axios.defaults.headers.common["Authorization"] = "Bearer " + token;
       commit('LOGIN_SUCCESS', token, user)

登录时,该操作调用一个端点,该端点返回一个存储在本地存储中的令牌。令牌也附加到 axios 默认标头中,因此我不必每次想在应用程序中进行 axios 调用时都附加令牌。

现在开始测试。我编写了一个成功模拟 axios 帖子的测试,但是在为模拟设置默认标头时失败并出现错误。

这是错误

TypeError: Cannot read property 'headers' of undefined

  37 |           const user = resp.data.user
  38 |           localStorage.setItem('token', token)
> 39 |           axios.defaults.headers.common["Authorization"] = "Bearer " + token;
     |                          ^
  40 |           commit('LOGIN_SUCCESS', token, user)
  41 |           resolve(resp)
  42 |         )

这是包含模拟的测试

    import actions from "../../src/store/actions";

let url = "";
let body = "";

jest.mock("axios", () => (
  post: (_url, _body, config) =>  
    return new Promise((resolve) => 
        resolve('data' : 'success': 'token' : 'test')
    )
  ,


))


describe('login action', () => 
    it("let the user login and access login success mutator", async() => 
        const commit = jest.fn()
        const username = 'test'
        const password = 'test'

        await actions.login(commit, username, password)
    )
)

jest mock 是一个完整的 mock,它在调用时返回一个 Promise,其中包含我需要的数据,但是在尝试设置标头时代码会失败。有没有办法我也可以模拟这个,还是我需要以不同的方式编写模拟?

【问题讨论】:

通过使用名为 axios-mock-adapter 的包找到了解决此问题的方法,可以在此处找到 github.com/ctimmerm/axios-mock-adapter。这使用模拟适配器模拟 axios 并允许设置标头。然后我只测试 axios 对象上是否存在标头 【参考方案1】:

对于遇到相同问题的任何人,您都可以这样做。 Npm install axios-mock-adapter 然后使用下面的代码,但是根据你的需要改变它。

import actions from "../../src/store/actions";
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
describe('login action', () => 
    it("let the user login and access login success mutator", async() => 


        let mockAdapter = new MockAdapter(axios);

        mockAdapter.onPost('https://hotel-dev.devtropolis.co.uk/api/apilogin').reply(200, 
              token: 'test token',
              user: username: 'test', password: 'test'
          );


        const commit = jest.fn()
        const username = 'test'
        const password = 'test'

        await actions.login(commit, username, password)

    expect(axios.defaults.headers.common.Authorization).toBe('Bearer test token')

    expect(commit).toHaveBeenCalledWith(
      "LOGIN_SUCCESS",'test token', username, password)
    )

)

【讨论】:

以上是关于使用 jest 时 axios mock 无法处理默认标头的主要内容,如果未能解决你的问题,请参考以下文章

使用 Jest Mock Ajax

模拟内部 axios.create()

模拟 Axios 以测试 .catch()

如何使用 Jest 测试身份验证标头?

用 Jest 抛出的异步测试

如何在使用 jest 模拟 axios.get 时传递 AxiosPrmoise 类型值?