【问题标题】:Mocking a component method with Jest用 Jest 模拟组件方法
【发布时间】:2017-04-20 19:58:38
【问题描述】:

我有一个使用 fetch 与 API 对话的反应组件,它看起来像这样

class Customer extends Component {
  loadCustomer(id) {
    fetch(API + '/customers/' + id)
    .then((response) => response.json())
    .then((js) => {
       this.update(js);
    })
    .catch((error) => {
      console.error(error);
    }
  }
}

我正在尝试为它编写这样的笑话测试

jest.mock(Customer, () => {loadCustomer: jest.fn()});

describe('Customer', () => {
  it('renders customer', async  () => {
    const ret = `
    // sample json from the API
    `
    const result = Promise.resolve(ret);
    const tree = renderer.create(
      <Customer customerId={125}/>
    );
    loadCustomer.mockImplementation(() => result);
    await result;
    expect(tree.toJSON()).toMatchSnapshot();
  });
});

这失败了

 FAIL  tests/Customer.test.js
  ● Test suite failed to run

    TypeError: Cannot read property 'default' of undefined

      at Object.<anonymous> (tests/Customer.test.js:12:48)

有问题的线是 jest.mock(Customer, () =&gt; {loadCustomer: jest.fn()});

我在这里错过了什么?

编辑
如果我将违规行更改为 jest.mock(Customer, () =&gt; ({loadCustomer: jest.fn()})); 我明白了

FAIL  tests/Customer.test.js
  ● Test suite failed to run
    TypeError: Cannot read property 'default' of undefined

      at Object.<anonymous> (tests/Customer.test.js:12:48)
      at process._tickCallback (internal/process/next_tick.js:103:7)

编辑
如果我像这样模拟fetch 方法

beforeEach(() => {
  global.fetch = jest.fn().mockImplementation(() => {
    var p = new Promise((resolve, reject) => {
      resolve({
        json: function() {
          return { // some json }
        }
     return p;
    });
  });
});

describe('Customer', () => {
  it('renders customer', async () => {
    const tree = renderer.create(
      <Customer customerId={125}/>
    ).toJSON();
    await tree;
    expect(tree).toMatchSnapshot();
  });
});

那么测试不会等待获取完成。

【问题讨论】:

  • 您在模拟客户中没有返回任何内容。试试jest.mock(Customer, () =&gt; ({loadCustomer: jest.fn()}));
  • 这不起作用,因为jest.mock 需要一个作为模块路径的字符串,然后将其替换为作为第二个参数的函数的结果。为什么要在组件中模拟一个函数。最好只模拟fetch
  • 谢谢,确实解决了问题。我确实尝试在 beforeEach 块中模拟全局提取。但是如何在 it 函数中等待异步获取调用完成?
  • @AndreasKöberle 我添加了模拟全局获取函数的尝试!
  • 啊,我看到了问题,可以解决了。

标签: reactjs mocking jestjs


【解决方案1】:

模拟 fetch 时的问题是它返回了一个承诺,但您的测试没有等待或返回这个承诺,看看这个part of the docs 以了解问题。

var p
beforeEach(() => {
  var p = Promise.resolve({
    json: () => ({}),
  })
  global.fetch = () => p
});

describe('Customer', () => {
  it('renders customer', async () => {
    const tree = renderer.create(
      <Customer customerId={125} />,
    ).toJSON();
    await p;
    expect(tree).toMatchSnapshot();
  });
});

因此,您需要创建 Promise 并将其存储在一个变量中,以便您可以在测试中等待它。

【讨论】:

  • 谢谢,但这似乎不起作用。我有一个在加载数据时显示的文本块,我在我的快照中得到了它。
猜你喜欢
  • 1970-01-01
  • 2017-12-18
  • 2020-07-16
  • 2017-06-09
  • 2021-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-07
相关资源
最近更新 更多