javascript 在 Jest 中调用 React 的 this.props.onClick(this) 时我到底应该测试什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30034774/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 11:31:37  来源:igfitidea点击:

What exactly should I test when calling React's this.props.onClick(this) in Jest?

javascriptreactjsjestjs

提问by alengel

I've been writing tests for all my events (and everything else of course) but I'm at a loss on how to test that this.props.onClick(this) was called on a child component.

我一直在为我的所有事件(当然还有其他所有事件)编写测试,但我不知道如何测试 this.props.onClick(this) 是否在子组件上被调用。

My child component has the following code:

我的子组件具有以下代码:

closeModal: function() {
  this.props.onClick(this);
},

render: function() {
  return (
    <i className="close-icon" onClick={this.closeModal}></i>
  )
}

and the parent is listening to it like so:

父母正在听它像这样:

onCloseModal: function() {
  this.replaceState({
    modalStatus: 'hidden'
  });
},

render: function() {
  return (
    <QuestionModal modalStatus={this.state.modalStatus} onClick={this.onCloseModal} />
  )
}

I know how to test the parent's click event and I know how to call the child's button click event in the tests as well but I'm not sure what I should be exactly testing.

我知道如何测试父级的点击事件,我也知道如何在测试中调用子级的按钮点击事件,但我不确定我应该准确测试什么。

If I used Sinon and Jasmine, I would stub the closeModal method and check that it was called. Can I do that with Jest and if so how exactly?

如果我使用 Sinon 和 Jasmine,我会存根 closeModal 方法并检查它是否被调用。我可以用 Jest 做到这一点吗?如果可以,具体怎么做?

UPDATE

更新

I've tried writing a test based on @PhilVarg's answer but I'm not getting very far as I'm not able to mock closeModal.

我试过根据@PhilVarg 的回答编写一个测试,但我没有得到很远,因为我无法模拟closeModal

Here's my test:

这是我的测试:

      var closeIcon,
          myMock = jest.genMockFunction();

      form = TestUtils.renderIntoDocument(
        <QuestionForm />
      );
      form.closeModal = myMock;

      closeIcon = TestUtils.findRenderedDOMComponentWithClass(form, 'close-icon');

      TestUtils.Simulate.click(closeIcon);

      expect(form.closeModal).toBeCalled();

The test errors with Expected Function to be called.and closeModal is not mocked but still runs (I have a console log in it at the moment). I've been on it all afternoon but haven't been able to figure it out. Any help would be very appreciated.

调用预期函数的测试错误并且 closeModal 没有被模拟但仍然运行(我现在有一个控制台登录)。我整个下午都在研究它,但一直无法弄清楚。任何帮助将不胜感激。

采纳答案by alengel

Thanks to some of the suggestions from Phil, I finally figured it out. What I want to test is that closeModal is called when I click the icon. I have already tested that the parent component behaves as expected but I couldn't work out how to mock closeModal because I'm testing this specific component and by default, this is the only one Jest doesn't mock for me. I could stub it manually but that somehow didn't want to work.

感谢 Phil 的一些建议,我终于弄明白了。我要测试的是当我单击图标时调用 closeModal。我已经测试了父组件的行为是否符合预期,但我无法弄清楚如何模拟 closeModal,因为我正在测试这个特定的组件,默认情况下,这是唯一一个 Jest 不为我模拟的组件。我可以手动存根,但不知何故不想工作。

What I've done now is mock this.props.onClick within closeModal and I check that it fires.

我现在所做的是在 closeModal 中模拟 this.props.onClick 并检查它是否触发。

Here's how that looks in code:

这是代码中的样子:

describe('QuestionForm', function() {
  var onClickFunc,
      form;

  beforeEach(function() {
    onClickFunc = jest.genMockFunction();

    form = TestUtils.renderIntoDocument(
      <QuestionForm onClick={onClickFunc} />
    );
  });

  it('should call closeModal when the icon is clicked', function() {
    var closeIcon = TestUtils.findRenderedDOMComponentWithClass(form, 'close-icon');

    TestUtils.Simulate.click(closeIcon);

    expect(onClickFunc).toBeCalled();
  });

});

I think that sufficiently tests that closeModal behaves as expected.

我认为这足以测试 closeModal 的行为是否符合预期。

回答by PhilVarg

If you want to check that the function is called you'd want to use jest's toBeCalledfunction (or toBeCalledWith). Assuming you've done some set up to instantiate the components, renderIntoDocument, and simulate the click (checkout the tutorialif not)

如果您想检查该函数是否被调用,您需要使用 jest 的toBeCalled函数(或toBeCalledWith)。假设您已经完成了一些设置来实例化组件、renderIntoDocument 和模拟点击(如果没有,请查看教程

describe('#closeModal', function(){
  beforeEach(function(){
    // setup in here to instantiate / render component 
    // and simulate the click if the i tag
  })
  it('is called on click', function(){
    expect(questionModal.closeModal).toBeCalled()
  })
})

EDIT: Ok, so after tinkering with it, I was able to get a passing test doing something similar to your original structure. I created a mock function, but instead of doing form.closeModal = mock, I passed the mock into the Question as the onClick prop, and checked if it got called.

编辑:好的,所以在修改它之后,我能够通过与原始结构类似的测试。我创建了一个模拟函数,但没有执行 form.closeModal = mock,而是将模拟作为 onClick 道具传递到问题中,并检查它是否被调用。

describe('#closeModal', function(){
  var mock, form, closeIcon;

  beforeEach(function(){
    mock = jest.genMockFunction();
    form = TestUtils.renderIntoDocument(
      <QuestionForm onClick={ mock } />
    );
    closeIcon = TestUtils.findRenderedDOMComponentWithClass(form, 'close-icon');
    TestUtils.Simulate.click(closeIcon);
  })

  it('is called on click', function(){
    expect(mock).toBeCalled()
  })
})

回答by zemirco

You could use an asynchronous test. You have to call done()in your onClickhandler. If everything is fine the handler will call done()and the test passes. If the handler won't be called the test fails after some time because Jasmine cannot end it.

您可以使用异步测试。你必须调用done()你的onClick处理程序。如果一切正常,处理程序将调用done()并且测试通过。如果处理程序不会被调用,测试会在一段时间后失败,因为 Jasmine 无法结束它。

No need for stubbing or mocking.

无需存根或嘲笑。

it('should click', function(done) {
  function onClick() {
    done();
  }
  var instance = TestUtils.renderIntoDocument(
    <Component onClick={onClick} />
  );
  var button = TestUtils.findRenderedDOMComponentWithTag(instance, 'button');
  var buttonDOM = React.findDOMNode(button);
  React.addons.TestUtils.Simulate.click(buttonDOM);
});