javascript - 如何使用配置选项测试 axios

标签 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));  
}

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);
 });
});

也尝试了 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);
    });

抛出错误如下:
 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)

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

提前致谢!

最佳答案

单元测试解决方案:
index.js :

import axios from 'axios';

export function saveCourse(course) {
  const baseUrl = 'http://example.com/';
  const config = {
    method: course.id ? 'PUT' : 'POST',
    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));
}
index.test.js :

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

jest.mock('axios', () => jest.fn());

describe('60992357', () => {
  afterEach(() => {
    jest.restoreAllMocks();
  });
  it('should return data if status code equals 200', async () => {
    const mRes = { status: 200, data: 'fake data' };
    axios.mockResolvedValueOnce(mRes);
    const actual = await saveCourse({ id: 1 });
    expect(actual).toEqual('fake data');
    expect(axios).toBeCalledWith({
      method: 'PUT',
      url: 'http://example.com/1',
      headers: { 'content-type': 'application/json' },
      data: { id: 1 },
    });
  });

  it('should throw error if status code equals 400', async () => {
    const mRes = { status: 400, text: jest.fn().mockReturnValue('network') };
    axios.mockResolvedValueOnce(mRes);
    const logSpy = jest.spyOn(console, 'log');
    const actual = await saveCourse({ id: 1 });
    expect(actual).toBeUndefined();
    expect(axios).toBeCalledWith({
      method: 'PUT',
      url: 'http://example.com/1',
      headers: { 'content-type': 'application/json' },
      data: { id: 1 },
    });
    expect(mRes.text).toBeCalledTimes(1);
    expect(logSpy).toBeCalledWith(new Error('network'));
  });
});

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

 PASS  stackoverflow/60992357/index.test.js (9.916s)
  60992357
    ✓ should return data if status code equals 200 (7ms)
    ✓ should throw error if status code equals 400 (21ms)

  console.log node_modules/jest-environment-enzyme/node_modules/jest-mock/build/index.js:866
    Error: network
        at /Users/ldu020/workspace/github.com/mrdulin/react-apollo-graphql-starter-kit/stackoverflow/60992357/index.js:671:13
        at process._tickCallback (internal/process/next_tick.js:68:7)

----------|---------|----------|---------|---------|-------------------
File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
----------|---------|----------|---------|---------|-------------------
All files |     100 |       70 |     100 |     100 |                   
 index.js |     100 |       70 |     100 |     100 | 6,7,14            
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        11.848s

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

关于javascript - 如何使用配置选项测试 axios,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60992357/

相关文章:

java - 如何在 Intellij Idea 中自动移动单元测试类?

c# - .NET 任务/TPL 测试和模拟? (或者用法不正确?)

c# - 如何对返回 void 的方法进行单元测试?

python - 模拟 Googleads 进行单元测试

javascript - 代码 return val + '' === numVal + '' 的用途是什么?

javascript - 通过jquery显示json数据的值

javascript - 带有 ajax 和 Node http 模块的 Node.js 管道流

javascript - 并非所有链接都会触发 AJAX 调用,只有第一个链接会在 Python Flask 应用程序中触发

java - 我应该为 java.nio.Files 创建包装器以进行单元测试吗?

ruby - 为什么 Minitest 的 assert_raises 在这种情况下没有按预期工作?