首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >调用Jest spyOn函数

调用Jest spyOn函数
EN

Stack Overflow用户
提问于 2017-06-27 06:10:30
回答 3查看 132.8K关注 0票数 66

我正在尝试为一个简单的React组件编写一个简单的测试,并且我想使用Jest来确认当我用酶模拟单击时是否调用了一个函数。根据Jest文档,我应该能够使用spyOnspyOn

然而,当我尝试这样做时,我一直得到TypeError: Cannot read property '_isMockFunction' of undefined,我认为这意味着我的间谍是不确定的。我的代码如下所示:

代码语言:javascript
复制
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
class App extends Component {

  myClickFunc = () => {
      console.log('clickity clickcty')
  }
  render() {
    return (
      <div className="App">
        <div className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h2>Welcome to React</h2>
        </div>
        <p className="App-intro" onClick={this.myClickFunc}>
          To get started, edit <code>src/App.js</code> and save to reload.
        </p>
      </div>
    );
  }
}

export default App;

在我的测试文件中:

代码语言:javascript
复制
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { shallow, mount, render } from 'enzyme'

describe('my sweet test', () => {
 it('clicks it', () => {
    const spy = jest.spyOn(App, 'myClickFunc')
    const app = shallow(<App />)
    const p = app.find('.App-intro')
    p.simulate('click')
    expect(spy).toHaveBeenCalled()
 })
})

有谁知道我做错了什么吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-10-14 01:31:27

除了如何spyOn之外,您几乎完成了任何更改。当您使用spy时,您有两个选项:spyOn App.prototype或component component.instance()

方法const spy = jest.spyOn(Class.prototype,“”)

将spy附加到类prototype和呈现(浅层呈现)实例的顺序很重要。

代码语言:javascript
复制
const spy = jest.spyOn(App.prototype, "myClickFn");
const instance = shallow(<App />);

第一行上的App.prototype位就是让它工作所需的东西。在使用new MyClass()实例化JavaScript class或使用MyClass.prototype之前,它没有任何方法。对于您的特定问题,您只需要监视App.prototype方法myClickFn

jest.spyOn(component.instance(),“方法”)

代码语言:javascript
复制
const component = shallow(<App />);
const spy = jest.spyOn(component.instance(), "myClickFn");

此方法要求React.Componentshallow/render/mount实例可用。从本质上讲,spyOn只是在寻找可以劫持的东西,并将其推入jest.fn()。可能是:

一个普通的object

代码语言:javascript
复制
const obj = {a: x => (true)};
const spy = jest.spyOn(obj, "a");

一个class

代码语言:javascript
复制
class Foo {
    bar() {}
}

const nope = jest.spyOn(Foo, "bar");
// THROWS ERROR. Foo has no "bar" method.
// Only an instance of Foo has "bar".
const fooSpy = jest.spyOn(Foo.prototype, "bar");
// Any call to "bar" will trigger this spy; prototype or instance

const fooInstance = new Foo();
const fooInstanceSpy = jest.spyOn(fooInstance, "bar");
// Any call fooInstance makes to "bar" will trigger this spy.

或者是一个React.Component instance

代码语言:javascript
复制
const component = shallow(<App />);
/*
component.instance()
-> {myClickFn: f(), render: f(), ...etc}
*/
const spy = jest.spyOn(component.instance(), "myClickFn");

或者是一个React.Component.prototype

代码语言:javascript
复制
/*
App.prototype
-> {myClickFn: f(), render: f(), ...etc}
*/
const spy = jest.spyOn(App.prototype, "myClickFn");
// Any call to "myClickFn" from any instance of App will trigger this spy.

这两种方法我都用过,也见过。当我有一个beforeEach()beforeAll()块时,我可能会使用第一种方法。如果我只需要一个快速间谍,我会用第二个。只要注意固定间谍的顺序就行了。

编辑:如果你想检查你的myClickFn的副作用,你可以在一个单独的测试中调用它。

代码语言:javascript
复制
const app = shallow(<App />);
app.instance().myClickFn()
/*
Now assert your function does what it is supposed to do...
eg.
expect(app.state("foo")).toEqual("bar");
*/

编辑:这是一个使用功能组件的示例。请记住,在您的功能组件范围内的任何方法都不能用于监视。您将监视传递到您的函数组件中的函数属性,并测试这些属性的调用。这个示例探索了与jest.spyOn相对的jest.fn()的用法,两者都共享模拟函数API。虽然它没有回答最初的问题,但它仍然提供了对其他技术的见解,这些技术可以适用于与该问题间接相关的情况。

代码语言:javascript
复制
function Component({ myClickFn, items }) {
   const handleClick = (id) => {
       return () => myClickFn(id);
   };
   return (<>
       {items.map(({id, name}) => (
           <div key={id} onClick={handleClick(id)}>{name}</div>
       ))}
   </>);
}

const props = { myClickFn: jest.fn(), items: [/*...{id, name}*/] };
const component = render(<Component {...props} />);
// Do stuff to fire a click event
expect(props.myClickFn).toHaveBeenCalledWith(/*whatever*/);
票数 81
EN

Stack Overflow用户

发布于 2017-06-27 18:54:52

你就快到了。虽然我同意@Alex Young answer关于使用道具来实现这一点,但在尝试监视该方法之前,您只需引用instance即可。

代码语言:javascript
复制
describe('my sweet test', () => {
 it('clicks it', () => {
    const app = shallow(<App />)
    const instance = app.instance()
    const spy = jest.spyOn(instance, 'myClickFunc')

    instance.forceUpdate();    

    const p = app.find('.App-intro')
    p.simulate('click')
    expect(spy).toHaveBeenCalled()
 })
})

文档:http://airbnb.io/enzyme/docs/api/ShallowWrapper/instance.html

票数 28
EN

Stack Overflow用户

发布于 2017-06-27 07:55:47

在您的测试代码中,您试图将App传递给spyOn函数,但spyOn只能处理对象,而不能处理类。通常,您需要使用以下两种方法之一:

1)当点击处理程序调用作为属性传递的函数时,例如

代码语言:javascript
复制
class App extends Component {

  myClickFunc = () => {
      console.log('clickity clickcty');
      this.props.someCallback();
  }
  render() {
    return (
      <div className="App">
        <div className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h2>Welcome to React</h2>
        </div>
        <p className="App-intro" onClick={this.myClickFunc}>
          To get started, edit <code>src/App.js</code> and save to reload.
        </p>
      </div>
    );
  }
}

现在可以将spy函数作为道具传递给组件,并断言它被调用:

代码语言:javascript
复制
describe('my sweet test', () => {
 it('clicks it', () => {
    const spy = jest.fn();
    const app = shallow(<App someCallback={spy} />)
    const p = app.find('.App-intro')
    p.simulate('click')
    expect(spy).toHaveBeenCalled()
 })
})

2)点击处理程序在组件上设置某种状态,例如

代码语言:javascript
复制
class App extends Component {
  state = {
      aProperty: 'first'
  }

  myClickFunc = () => {
      console.log('clickity clickcty');
      this.setState({
          aProperty: 'second'
      });
  }
  render() {
    return (
      <div className="App">
        <div className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h2>Welcome to React</h2>
        </div>
        <p className="App-intro" onClick={this.myClickFunc}>
          To get started, edit <code>src/App.js</code> and save to reload.
        </p>
      </div>
    );
  }
}

您现在可以对组件的状态进行断言,即

代码语言:javascript
复制
describe('my sweet test', () => {
 it('clicks it', () => {
    const app = shallow(<App />)
    const p = app.find('.App-intro')
    p.simulate('click')
    expect(app.state('aProperty')).toEqual('second');
 })
})
票数 14
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44769404

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档