【问题标题】:Pass parameter to jest.mock将参数传递给 jest.mock
【发布时间】:2020-05-02 10:05:03
【问题描述】:

我有一个模拟如下

jest.mock('react-hook-inview', () => {
  const setRef = jest.fn();
  const observer = jest.fn();
  const intersecting = true;
  const entry = {
    y: 0,
  };
  return [setRef, intersecting, entry, observer];
});

在这里我想更改intersecting 的值。如何将其从一项测试更改为另一项测试?我试图使用类似工厂的东西:

const inView = (intersecting) => {
  jest.mock('react-hook-inview', () => {
    const setRef = jest.fn();
    const observer = jest.fn();
    const entry = {
      y: 0,
    };
    return [setRef, intersecting, entry, observer];
  });
}

并像使用它

  it('is invisible by default', () => {
    const text = 'Test';
    const { container } = render(<Reveal>{text}</Reveal>);
    inView(false);
    expect(container.firstChild).not.toBeVisible();
  });

  it('is visible when in view', () => {
    const text = 'Test';
    const { container } = render(<Reveal>{text}</Reveal>);
    inView(true);
    expect(container.firstChild).toBeVisible();
  });

但是这会抛出

The module factory of `jest.mock()` is not allowed to reference any out-of-scope variables.
Invalid variable access: intersecting

有人有想法吗?

干杯!

编辑:

我现在的解决方案是像这样模拟它

import ReactHookInview from 'react-hook-inview';

jest.mock('react-hook-inview', () => ({
  useInView: jest.fn().mockImplementation(() => {
    const setRef = jest.fn();
    const observer = jest.fn();
    const intersecting = false;
    const entry = {
      boundingClientRect: {
        y: 0,
      },
    };
    return [setRef, intersecting, entry, observer];
  }),
}));

在我的测试中,我会这样覆盖:

ReactHookInview.useInView.mockImplementation(() => {
  const setRef = jest.fn();
  const observer = jest.fn();
  const intersecting = true;
  const entry = {
    boundingClientRect: {
      y: 1,
    },
  };
  return [setRef, intersecting, entry, observer];
});

但这不是很漂亮

【问题讨论】:

  • 您将const intersecting = true 留在了屏蔽传递参数intersecting 的函数中。我不认为这会解决你的问题,尽管因为开玩笑提升了模块模拟。
  • @DrewReese 我对此表示怀疑,因为 Jest 不允许闭包样式引用变量。这可能是因为 Jest 提升了 mocks。
  • @DrewReese 好眼光!不幸的是,我只是把它留在这里,但在我的实际代码中没有犯这个错误:D 我还更新了我的初始帖子

标签: javascript reactjs jestjs react-testing-library


【解决方案1】:

您可以像已经完成的那样模拟您的库,导入它并明确设置它的值。然后之前有两组不同的测试:

jest.mock('react-hook-inview', /* as above */ );

import rhi from 'react-hook-inview';

describe('my implementation', () => {

  describe('while intersecting', () => {
    let result;
    beforeAll(() => {
      rhi[1] = true;
      result = myImplementationUsingIntersecting();
    });

    it('should result X', () => {
      expect(result).toEqual(X);
    });
  });

  describe('while NOT intersecting', () => {
    let result;
    beforeAll(() => {
      rhi[1] = false;
      result = myImplementationUsingIntersecting();
    });

    it.todo('should result Y');
  });
})

working example

编辑 2:为了正确模拟 React 钩子

因为反应钩子是返回东西的函数,你可以像这样模拟它

jest.mock('react-hook-inview', () => jest.fn());
// and you can take it's reference with import
import useInView from 'react-hook-inview';
// and then you can mock it's return value as array
beforeAll(() => {
  useInView.mockReturnValue(['a', true, 'b', 'c']);
  result = myImplementationUsingIntersecting();
})

【讨论】:

  • 感谢您的回答!我试图调整你的解决方案。例如,我必须使用const [setRef, intersecting, entry, observer] = rhi.useInView();,当然还要用上面提到的实现更改myImplementationUsingIntersecting,但它不起作用。我也不明白为什么这应该起作用?我的意思是如果我在我的beforeAll 钩子中更改解构intersecting 的值.. 为什么我的实现要使用它?而且我想情况也并非如此。
  • @MarcMintel 抱歉,我的回答只是一个解决方案大纲我没有测试过,但现在我已经更新了它并添加了工作示例
  • @MarcMintel 所以基本上jest.mock 正在返回一个数组,您可以修改它的[1] 属性,这是将在实现中使用的intersecting
  • 感谢您的解释!这对我来说更有意义。但是我仍然无法正常工作。也许那是因为rhi 不是返回一个数组,而是一个带有useInView 方法的对象,它返回一个数组?但我也尝试更改rhi.useInView[1],但没有成功。
  • 谢谢!这与我的“当前解决方法”非常相似。我不喜欢这个解决方案的地方是,我必须知道回报的每一个值。如果我可以传递一个 true 或 false 作为参数,它会让事情变得更容易......或者可能调用一个改变相交值的方法。例如,我还必须更改 entry.boundingClientRecty 值,而这里的事情开始变得有点过于复杂,无法更改每个测试中的值。
猜你喜欢
  • 2019-09-27
  • 1970-01-01
  • 1970-01-01
  • 2013-01-27
  • 2013-11-19
  • 2011-01-06
  • 2013-07-19
  • 2011-02-09
相关资源
最近更新 更多