TypeError:无法读取未定义的属性(阅读'then')- axios post nodejs jest

ny6fqffe  于 2022-11-23  发布在  iOS
关注(0)|答案(2)|浏览(234)

我正在尝试使用jest为axios post请求编写一个单元测试。这是我的实际功能-

exports.getAccessToken = function (urlToCall, scope, basicAuthToken) {
  return new Promise(function (resolve, reject) {
    let axios = require("axios");
    let qs = require("qs");
    let data = qs.stringify({
      grant_type: "client_credentials",
      scope: scope,
    });
    let config = {
      method: "post",
      url: urlToCall,
      headers: {
        "Content-Type": "application/x-www-form-urlencoded",
        Authorization: "Basic " + basicAuthToken,
      },
      data: data,
    };

    axios(config)
      .then(function (response) {
        resolve(response.data);
      })
      .catch(function (error) {
        console.log(
          "error occurred while getting access token for the scope - ",
          scope,
          " and the error is - ",
          error
        );
      });
  });
};

这是我的单元测试代码-

const processUtils = require('../src/utils/process-utils')
const axios = require('axios')
jest.mock("axios")
describe("when getAccessToken API is successful", () => {
    test('should return access token', async () => {
        const expectedResponse = JSON.stringify({
            "access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6ImMxZDY2OTF",
            "issued_token_type": "token-type:access_token",
            "token_type": "Bearer",
            "expires_in": 3600,
            "scope": "consumer_profile:read:"
        })
        axios.post.mockResolvedValueOnce(() => Promise.resolve(expectedResponse))
        // axios.post.mockImplementationOnce(() => Promise.resolve(expectedResponse));

        let urlToCall = 'https://somehost.com/access_token/v1'
        let scope = jest.fn
        let basicAuthToken = jest.fn

        const response = await processUtils.getAccessToken(urlToCall, scope, basicAuthToken)

        expect(mockAxios.post).toHaveBeenCalledWith(urlToCall)
        expect(response).toEqual(expectedResponse)
    });
});

这是运行jest -

TypeError: Cannot read properties of undefined (reading 'then')

> axios(config)
    .then(function (response) {
       resolve(response.data);
    })

https://i.stack.imgur.com/NZiVp.png我是节点和笑话的新手。有人能告诉我我在这里遗漏了什么吗?

fkaflof6

fkaflof61#

这个问题是由于你的代码没有直接调用axios模块示例上的post函数,而是通过config隐式调用,而你的测试模拟是直接调用axios.post。有两种方法可以解决这个问题。
1.将隐式post调用更改为显式调用:
发件人:

axios(config).then(function (response) {

收件人:

axios.post(config.url, config.data, { headers: config.headers }).then(function (response) {

这将使用axios.post.mockResolvedValueOnce调用的结果。
1.在测试套件设置中模拟axios post调用:
发件人:

jest.mock("axios")

结束日期

jest.mock("axios", () => {
  const expectedResponse = JSON.stringify({
    "access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6ImMxZDY2OTF",
    "issued_token_type": "token-type:access_token",
    "token_type": "Bearer",
    "expires_in": 3600,
    "scope": "consumer_profile:read:"
  });
  return () => new Promise((resolve) => resolve(expectedResponse));
})

这将通过partialmock模拟隐式post调用,但是您将无法直接访问post方法,因此您将无法侦听其调用。
另一个小注意事项,当then被调用时,axios.post.mockResolvedValueOnce(() => Promise.resolve(expectedResponse))会将一个函数传递到response参数中。我认为您需要使用mockedAxios.post.mockResolvedValueOnce(expectedResponse)。另外,expectedResponse应该被 Package 在data属性中,如下所示:

const expectedResponse = JSON.stringify({
  "data": {
    "access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6ImMxZDY2OTF",
    "issued_token_type": "token-type:access_token",
    "token_type": "Bearer",
    "expires_in": 3600,
    "scope": "consumer_profile:read:"
  }
});
oogrdqng

oogrdqng2#

我试图张贴的解决方案,使它能帮助别人。解决方案是根据Ovidijus Parsiunas的回应找到的。实际功能:

exports.getAccessToken = function (urlToCall, scope, basicAuthToken) {
  return new Promise(function (resolve, reject) {
    let axios = require("axios");
    let qs = require("qs");
    let data = qs.stringify({
      grant_type: "client_credentials",
      scope: scope,
    });
    const requestHeaders = {
      "Content-Type": "application/x-www-form-urlencoded",
      Authorization: "Basic " + basicAuthToken,
    };
    // axios(config)
    axios
      .post(urlToCall, data, {
        headers: requestHeaders,
      })
      .then(function (response) {
        resolve(response.data);
      })
      .catch(function (error) {
        console.log(
          "error occurred while getting access token for the scope - ",
          scope,
          " and the error is - ",
          error
        );
      });
  });
};

我的单元测试用例:

const processUtils = require('../src/utils/process-utils')
const axios = require('axios')
jest.mock("axios", () => ({
  post: jest.fn(() => {
    const expectedResponse = {
      access_token: "eyJhbGciOiJSUzI1NiIsImtpZCI6ImMxZDY2OTF",
      issued_token_type: "token-type:access_token",
      token_type: "Bearer",
      expires_in: 3600,
      scope: "consumer_profile:read:",
    };
    // return () => new Promise((resolve) => resolve(expectedResponse));
    return expectedResponse;
  }),
}));
describe("when getAccessToken API is successful", () => {
  it("should return access token", async () => {
    const expectedResponse = {
      data: {
        access_token: "eyJhbGciOiJSUzI1NiIsImtpZCI6ImMxZDY2OTF",
        issued_token_type: "token-type:access_token",
        token_type: "Bearer",
        expires_in: 3600,
        scope: "consumer_profile:read:",
      },
    };

    axios.post.mockResolvedValueOnce(expectedResponse);

    let urlToCall =
      "https://somehost.com/access_token/v1";
    let scope = jest.fn();
    let basicAuthToken = jest.fn();

    const response = await processUtils.getAccessToken(
      urlToCall,
      scope,
      basicAuthToken
    );
    console.log("response - ", response);
    expect(response).toEqual(expectedResponse.data);
  });

相关问题