如何使用配置选项测试 axios

Suc*_*ta 4 javascript unit-testing mocking jestjs axios

我正在尝试测试以下为 put/post 作为配置选项编写的 axios 请求:

export function saveCourse(course){
  const config = {
      method: course.id ? 'PUT' : 'POST',// POST for create, PUT to update when id already exists.
      url: baseUrl + (course.id || ''),
      headers: { "content-type": "application/json" },
      data: course
  }
  return axios(config)
  .then((res) => {
      if(res.status === 201 || res.status === 200) return res.data;
      if(res.status === 400){
          const error = res.text();
          throw new Error(error);
      }
  })
  .catch((err) => console.log(err));  
}
Run Code Online (Sandbox Code Playgroud)

courseApi.test.js 如下所示:

import { saveCourse } from './courseApi';
import axios from 'axios';

jest.mock('axios');

describe('check API calls', () => {
 it('should update the course', () => {
    let res = {
      id: 10,
      title: "Securing React Apps with Auth0",
      slug: "react-auth0-authentication-security",
      authorId: 2,
      category: "JavaScript"
    };

    const config = {
        method: 'put',
        url: 'http://localhost:3001/courses/10',
        headers: { "content-type": "application/json" },
        data: res
      }
    }

  axios = jest.fn().mockResolvedValue({
        status: 200,
        data: res
      });
      let result = await saveCourse(res);
      expect(result).toEqual(res);
      // expect(axiosMock.put).toHaveBeenCalledTimes(1);
 });
});
Run Code Online (Sandbox Code Playgroud)

也尝试使用mockImplementationOnce,在这种情况下,模拟axios没有被调用。

it("save course scenario", async function () {
    const course = {
      id: 10,
      title: "Securing React Apps with Auth0",
      slug: "react-auth0-authentication-security",
      authorId: 2,
      category: "JavaScript"
    };
    axios.put.mockImplementationOnce(() => Promise.resolve(course));
    expect(saveCourse(course)).resolves.toEqual(course);
    expect(axios.put).toHaveBeenCalledTimes(1);
    });
Run Code Online (Sandbox Code Playgroud)

抛出错误如下:

 TypeError: Cannot read property 'then' of undefined

      24 |       data: course
      25 |   }
    > 26 |   return axios(config)
         |          ^
      27 |   .then((res) => {
      28 |       if(res.status === 201) { console.log(res); return res.data; }
      29 |       if(res.status === 200) { console.log(res); return res.data; }

      at saveCourse (src/api/courseApi.js:26:10)
      at Object.<anonymous> (src/api/courseApi.test.js:39:12)
Run Code Online (Sandbox Code Playgroud)

那么我应该如何解决这个问题,我错过了为 axios 模拟设置的任何内容?

提前致谢!

sli*_*wp2 7

单元测试解决方案:

\n\n

index.js:

\n\n
import axios from \'axios\';\n\nexport function saveCourse(course) {\n  const baseUrl = \'http://example.com/\';\n  const config = {\n    method: course.id ? \'PUT\' : \'POST\',\n    url: baseUrl + (course.id || \'\'),\n    headers: { \'content-type\': \'application/json\' },\n    data: course,\n  };\n  return axios(config)\n    .then((res) => {\n      if (res.status === 201 || res.status === 200) return res.data;\n      if (res.status === 400) {\n        const error = res.text();\n        throw new Error(error);\n      }\n    })\n    .catch((err) => console.log(err));\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

index.test.js:

\n\n
import { saveCourse } from \'./\';\nimport axios from \'axios\';\n\njest.mock(\'axios\', () => jest.fn());\n\ndescribe(\'60992357\', () => {\n  afterEach(() => {\n    jest.restoreAllMocks();\n  });\n  it(\'should return data if status code equals 200\', async () => {\n    const mRes = { status: 200, data: \'fake data\' };\n    axios.mockResolvedValueOnce(mRes);\n    const actual = await saveCourse({ id: 1 });\n    expect(actual).toEqual(\'fake data\');\n    expect(axios).toBeCalledWith({\n      method: \'PUT\',\n      url: \'http://example.com/1\',\n      headers: { \'content-type\': \'application/json\' },\n      data: { id: 1 },\n    });\n  });\n\n  it(\'should throw error if status code equals 400\', async () => {\n    const mRes = { status: 400, text: jest.fn().mockReturnValue(\'network\') };\n    axios.mockResolvedValueOnce(mRes);\n    const logSpy = jest.spyOn(console, \'log\');\n    const actual = await saveCourse({ id: 1 });\n    expect(actual).toBeUndefined();\n    expect(axios).toBeCalledWith({\n      method: \'PUT\',\n      url: \'http://example.com/1\',\n      headers: { \'content-type\': \'application/json\' },\n      data: { id: 1 },\n    });\n    expect(mRes.text).toBeCalledTimes(1);\n    expect(logSpy).toBeCalledWith(new Error(\'network\'));\n  });\n});\n
Run Code Online (Sandbox Code Playgroud)\n\n

带有覆盖率报告的单元测试结果:

\n\n
 PASS  stackoverflow/60992357/index.test.js (9.916s)\n  60992357\n    \xe2\x9c\x93 should return data if status code equals 200 (7ms)\n    \xe2\x9c\x93 should throw error if status code equals 400 (21ms)\n\n  console.log node_modules/jest-environment-enzyme/node_modules/jest-mock/build/index.js:866\n    Error: network\n        at /Users/ldu020/workspace/github.com/mrdulin/react-apollo-graphql-starter-kit/stackoverflow/60992357/index.js:671:13\n        at process._tickCallback (internal/process/next_tick.js:68:7)\n\n----------|---------|----------|---------|---------|-------------------\nFile      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s \n----------|---------|----------|---------|---------|-------------------\nAll files |     100 |       70 |     100 |     100 |                   \n index.js |     100 |       70 |     100 |     100 | 6,7,14            \n----------|---------|----------|---------|---------|-------------------\nTest Suites: 1 passed, 1 total\nTests:       2 passed, 2 total\nSnapshots:   0 total\nTime:        11.848s\n
Run Code Online (Sandbox Code Playgroud)\n\n

源代码:https://github.com/mrdulin/react-apollo-graphql-starter-kit/tree/master/stackoverflow/60992357

\n