首页 > 解决方案 > 尝试使用 Mocha & Sinon 存根 HTTP 调用。收到的错误:TypeError:预期会产生,但没有通过回调

问题描述

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

我创建了一个function使用Axios来获取所有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 };

标签: javascriptnode.jsunit-testingaxiosmocha.js

解决方案


我能够getALLTodos通过存根Axios和它的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();
  });
});

推荐阅读