Trying to stub an HTTP call with Mocha & Sinon. Received Error: TypeError: get expected to yield, but no callback was passed

Trying to stub an HTTP call with Mocha & Sinon. Received Error: TypeError: get expected to yield, but no callback was passed

我一直在练习使用 JSONPlaceholder, Mocha, Chai & Sinon 存根来掌握这一点,稍后我将对 HTTP 调用的实际实现进行单元测试。

我使用 Axios 创建了一个 function 来获取所有 todos 并导出为存根,如下所示:

const axios = require('axios');

const getAllTodos = () => {
  return axios.get('https://jsonplaceholder.typicode.com/todos').then(response => response);
};

module.exports = { getAllTodos };

然后我试着像这样存根:

const { expect } = require('chai');
const sinon = require('sinon');
const axios = require('axios');

const { getAllTodos } = require('correct/path/to/method');

describe('Testing the todos HTTP call', () => {
  before(() => {
      sinon.stub(axios, 'get').yields(null, null, JSON.stringify([
        {
          userId: 1,
          id: 1,
          title: "delectus aut autem",
          completed: false
          },
      ]))
    });

    after(() => {
      axios.get.restore();
    });

  it('should return all todos', done => {
    getAllTodos().then(todos => {
      todos.data.forEach(todo => {
        expect(todo).to.have.property('userId');
        expect(todo).to.have.property('id');
        expect(todo).to.have.property('title');
        expect(todo).to.have.property('completed');
      });
      done();
    }).catch(done, done);
  });
});

但是,我收到以下错误:

1) Testing the todos HTTP call
       should return all todos:
     TypeError: get expected to yield, but no callback was passed. Received [https://jsonplaceholder.typicode.com/todos]

如果我对 function 进行单元测试而不对它进行存根。它就像一个魅力。这是没有打桩的单元测试:

const { expect } = require('chai');
const { getAllTodos } = require('correct/path/to/method');

describe('Testing the todos HTTP call', () => {
  it('should return all todos', done => {
    getAllTodos().then(todos => {
      todos.data.forEach(todo => {
        expect(todo).to.have.property('userId');
        expect(todo).to.have.property('id');
        expect(todo).to.have.property('title');
        expect(todo).to.have.property('completed');
      });
      done();
    }).catch(done, done);
  });
});

我得到 function 通过正确的断言正确传递:


Testing the todos HTTP call
    ✓ should return all todos (169ms)

我该如何解决这个问题?我做错了什么?我需要一个初学者友好的解释来将这个解决方案转化为我自己的实现。

编辑:

我一直在尝试其他方法来存根 HTTP 调用,它适用于互联网,但是一旦我关闭互联网... stub 失败。这是我的最新代码:

describe('Testing the todos HTTP call', () => {
  let stub;

  beforeEach(() => {
    stub = sinon.stub({ getAllTodos }, 'getAllTodos');
  });

  afterEach(() => {
    stub.restore();
  });

  it('should return all todos with the right properties', () => {
    const mockedResponseObj = {
      userId: 1,
      id: 1,
      title: 'This is title',
      completed: true,
    };

    stub
      .withArgs('https://jsonplaceholder.typicode.com/todos')
      .returns(Promise.resolve(mockedResponseObj));

    const result = getAllTodos('https://jsonplaceholder.typicode.com/todos');

    expect(result.data[0]).to.have.property('userId');
    expect(result.data[0]).to.have.property('id');
    expect(result.data[0]).to.have.property('title');
    expect(result.data[0]).to.have.property('completed');
  });
});

&导出的function最新代码:

const axios = require('axios');

const getAllTodos = url => {
  return axios.get(url).then(response => response);
};

module.exports = { getAllTodos };

我能够通过存根 Axios 来对 getALLTodos 方法进行单元测试,它是 GET 方法,而不是像这样:

describe('Testing the todos HTTP call', () => {
  let stub;

  const mockedResponseObj = {
    userId: 1,
    id: 1,
    title: 'This is title',
    completed: true,
  };

  beforeEach(() => {
    stub = sinon.stub(axios, 'get').resolves(mockedResponseObj);
  });

  afterEach(() => {
    stub.restore();
  });

  it('should return all todos with the right properties', done => {
    getAllTodos('https://jsonplaceholder.typicode.com/todos').then(res => {
      expect(res.data[0]).to.have.keys(Object.keys(mockedResponseObj));
    });
    done();
  });
});