调用 Jest spyOn 函数 [英] Jest spyOn function called

查看:30
本文介绍了调用 Jest spyOn 函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试为一个简单的 React 组件编写一个简单的测试,并且我想使用 Jest 来确认当我用酶模拟点击时已经调用了一个函数.根据 Jest 文档,我应该能够使用 spyOn 来做到这一点:间谍.

但是,当我尝试此操作时,我不断收到 TypeError: Cannot read property '_isMockFunction' of undefined 这意味着我的间谍未定义.我的代码如下所示:

import React, { Component } from 'react';从'./logo.svg'导入标志;导入'./App.css';类 App 扩展组件 {myClickFunc = () =>{console.log('clickity clickcty')}使成为() {返回 (<div className="应用程序"><div className="App-header"><img src={logo} className="App-logo" alt="logo"/><h2>欢迎反应</h2>

<p className="App-intro" onClick={this.myClickFunc}>首先,编辑 src/App.js;并保存以重新加载.</p>

);}}导出默认应用程序;

在我的测试文件中:

从'react'导入React;从 'react-dom' 导入 ReactDOM;从'./App'导入应用程序;从'酶'导入{浅,安装,渲染}描述('我的甜蜜测试',()=> {it('点击它', () => {const spy = jest.spyOn(App, 'myClickFunc')const app = 浅()const p = app.find('.App-intro')p.simulate('点击')期望(间谍).toHaveBeenCalled()})})

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

解决方案

除了 spyOn 之外,您几乎没有任何变化.当你使用spy时,你有两个选择:spyOnApp.prototype,或者组件component.instance().


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

在类原型上附加间谍和渲染(浅渲染)实例的顺序很重要.

const spy = jest.spyOn(App.prototype, myClickFn");const 实例 = 浅();

第一行的 App.prototype 位是你需要的东西.JavaScript class 没有它的任何方法,直到你用 new MyClass() 实例化它,或者你深入到 MyClass.prototype.对于您的特定问题,您只需要监视 App.prototype 方法 myClickFn.


jest.spyOn(component.instance(), 方法")

const component = Shallow();const spy = jest.spyOn(component.instance(), myClickFn");

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

一个普通的object:

const obj = {a: x =>(真的)};const spy = jest.spyOn(obj, a");

一个:

class Foo {酒吧() {}}const nope = jest.spyOn(Foo, bar");//抛出错误.Foo 没有酒吧"方法.//只有 Foo 的一个实例有bar".const fooSpy = jest.spyOn(Foo.prototype, bar");//对bar"的任何调用会触发这个间谍;原型或实例const fooInstance = new Foo();const fooInstanceSpy = jest.spyOn(fooInstance, bar");//fooInstance 对bar"的任何调用会触发这个间谍.

或者一个 React.Component 实例:

const component = Shallow();/*组件实例()->{myClickFn: f(), 渲染: f(), ...等}*/const spy = jest.spyOn(component.instance(), myClickFn");

或者一个React.Component.prototype:

/*App.prototype->{myClickFn: f(), 渲染: f(), ...等}*/const spy = jest.spyOn(App.prototype, myClickFn");//对myClickFn"的任何调用来自 App 的任何实例都会触发这个间谍.

我已经使用并看过这两种方法.当我有一个 beforeEach()beforeAll() 块时,我可能会采用第一种方法.如果我只需要一个快速间谍,我会使用第二个.只需注意附加间谍的顺序即可.


如果您想检查 myClickFn 的副作用,您可以在单独的测试中调用它.

const app = Shallow();app.instance().myClickFn()/*现在断言你的函数做了它应该做的......例如.expect(app.state("foo")).toEqual("bar");*/

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

function Component({ myClickFn, items }) {const handleClick = (id) =>{返回 () =>myClickFn(id);};返回 (<>{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}/>);//做一些事情来触发点击事件期望(props.myClickFn).toHaveBeenCalledWith(/*whatever*/);

I'm trying to write a simple test for a simple React component, and I want to use Jest to confirm that a function has been called when I simulate a click with enzyme. According to the Jest docs, I should be able to use spyOn to do this: spyOn.

However, when I try this, I keep getting TypeError: Cannot read property '_isMockFunction' of undefined which I take to mean that my spy is undefined. My code looks like this:

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;

and in my test file:

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()
 })
})

Anyone have an insight into what I'm doing wrong?

解决方案

You were almost done without any changes besides how you spyOn. When you use the spy, you have two options: spyOn the App.prototype, or component component.instance().


const spy = jest.spyOn(Class.prototype, "method")

The order of attaching the spy on the class prototype and rendering (shallow rendering) your instance is important.

const spy = jest.spyOn(App.prototype, "myClickFn");
const instance = shallow(<App />);

The App.prototype bit on the first line there are what you needed to make things work. A JavaScript class doesn't have any of its methods until you instantiate it with new MyClass(), or you dip into the MyClass.prototype. For your particular question, you just needed to spy on the App.prototype method myClickFn.


jest.spyOn(component.instance(), "method")

const component = shallow(<App />);
const spy = jest.spyOn(component.instance(), "myClickFn");

This method requires a shallow/render/mount instance of a React.Component to be available. Essentially spyOn is just looking for something to hijack and shove into a jest.fn(). It could be:

A plain object:

const obj = {a: x => (true)};
const spy = jest.spyOn(obj, "a");

A class:

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.

Or a React.Component instance:

const component = shallow(<App />);
/*
component.instance()
-> {myClickFn: f(), render: f(), ...etc}
*/
const spy = jest.spyOn(component.instance(), "myClickFn");

Or a React.Component.prototype:

/*
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.

I've used and seen both methods. When I have a beforeEach() or beforeAll() block, I might go with the first approach. If I just need a quick spy, I'll use the second. Just mind the order of attaching the spy.


EDIT: If you want to check the side effects of your myClickFn you can just invoke it in a separate test.

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");
*/

EDIT: Here is an example of using a functional component. Keep in mind that any methods scoped within your functional component are not available for spying. You would be spying on function props passed into your functional component and testing the invocation of those. This example explores the use of jest.fn() as opposed to jest.spyOn, both of which share the mock function API. While it does not answer the original question, it still provides insight on other techniques that could suit cases indirectly related to the question.

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*/);

这篇关于调用 Jest spyOn 函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆