Javascript 在酶中,如何从功能成分的支柱中获得功能?

Javascript 在酶中,如何从功能成分的支柱中获得功能?,javascript,reactjs,jestjs,enzyme,Javascript,Reactjs,Jestjs,Enzyme,我正在使用Jest和Ezyme为我的react项目编写单元测试 如下所示,我通过props将名为updateUser的函数传递给待测试组件EditCard description('编辑卡屏幕',()=>{ 让包装纸; 在每个之前(()=>{ const defaultProps:Partial={ toggleEditing:jest.fn(), 用户:mockUsers[0], updateUser:jest.fn(),//通过props将此函数传递给“EditCard”组件 showSna

我正在使用Jest和Ezyme为我的react项目编写单元测试

如下所示,我通过props将名为
updateUser
的函数传递给待测试组件
EditCard

description('编辑卡屏幕',()=>{
让包装纸;
在每个之前(()=>{
const defaultProps:Partial={
toggleEditing:jest.fn(),
用户:mockUsers[0],
updateUser:jest.fn(),//通过props将此函数传递给“EditCard”组件
showSnackbar:jest.fn(),
};
包装器=浅();
});
然后,我想测试在模拟单击按钮后调用它的次数

it('在未填写“Name”文本字段且单击“submit”按钮时,应与快照匹配',()=>{
find('#Name').simulate('change',{target:{value:null}});
wrapper.find(“#submit”).simulate('click');
//尝试从道具中获取“updateUser”函数,但获取“undefined”。
期望(wrapper.prop('updateUser')).toHaveBeenCalledTimes(0);
});
但我得到的错误如下所示:

    Matcher error: received value must be a mock or spy function

    Received has value: undefined

      24 |     wrapper.find('#Name').simulate('change', { target: { value: null } });
      25 |     wrapper.find('#submit').simulate('click');
    > 26 |     expect(wrapper.prop('updateUser')).toHaveBeenCalledTimes(0);
有人能告诉我哪里做错了吗?为什么我不能从道具中获取函数,并且返回了
未定义的


提前感谢!

对您的代码进行一些调整应该可以让它正常工作

import * as React from "react";
import { mount, ReactWrapper } from "enzyme";
import EditCard from "../path/to/EditCard";

/* 
  I'd recommend defining jest fns here to make them easier to reference anywhere
  within the tests below; otherwise, it'll have to referenced via 
  'defaultProps.updateUser', 'defaultProps.showSnackbar', ...etc. 
  Using 'const' here allows us to define these variables within the 
  module's closure -- in short, only accessible within these tests and NOT 
  globally accessible (from other file tests).
*/
const showSnackbar = jest.fn();
const toggleEditing = jest.fn();
const updateUser = jest.fn();

/* 
  if the EditCard component is properly typed, then you shouldn't need to
  add types to this 'defaultProps' object
*/
const defaultProps = {
  showSnackbar,
  toggleEditing,
  updateUser,
  user: mockUsers[0]
};

describe('The EditCard screen', () => {
  let wrapper: ReactWrapper;
  beforeEach(() => {
    /* 
      I'd recommend mount over shallow because child components can be 
      deeply nested and require multiple .dive calls; however, if 
      you know the child components of "EditCard" are just simple JSX elements, 
      then shallow will be fine
    */
    wrapper = mount(<EditCard {...defaultProps} />);
  });

  it("should not call 'updateUser' when the form is submitted with an empty '#Name' field", () => {
    /*
      I'm not sure what simulating "null" does for this input, but assuming this
      input is required you should at least pass a string value -- assuming
      "#Name" input is of type 'text' | 'password' | 'email' => string and 
      not a number. On a related note, if it's required, then simply remove this 
      code as it doesn't do much for the test.
    */
    // wrapper.find('#Name').simulate('change', { target: { value: "" } });

    /*
      I'm assuming this then simulates a form submit. Unfortunately,
      pressing the submit button won't work. Instead you'll have to 
      simulate a form submit. This is a limitation of Enzyme and last I 
      checked hasn't been/can't be fixed.
    */
    wrapper.find('form').simulate('submit');
    
    /*
     it should then NOT call the jest.fn() "updateUser" when submitted since 
     '#Name' is empty. Notice that we're referencing 'updateUser' -- the jest fn
     defined above -- and not the wrapper.prop fn.
    */ 
    expect(updateUser).not.toHaveBeenCalled();
  });
  
  // include other tests...
});

import*as React from“React”;
从“酶”导入{mount,ReactWrapper};
从“./path/to/EditCard”导入EditCard;
/* 
我建议在这里定义jest FN,以便于在任何地方引用
在下面的测试中;否则,必须通过
“defaultProps.updateUser”、“defaultProps.showSnackbar”等。
这里使用“const”允许我们在
模块的闭包——简言之,只能在这些测试中访问,而不能访问
全局可访问(从其他文件测试)。
*/
const showSnackbar=jest.fn();
const-toggleEditing=jest.fn();
const updateUser=jest.fn();
/* 
如果EditCard组件键入正确,则不需要
将类型添加到此“defaultProps”对象
*/
const defaultProps={
showSnackbar,
切换编辑,
更新者,
用户:mockUsers[0]
};
描述('编辑卡屏幕',()=>{
让包装器:反应包装器;
在每个之前(()=>{
/* 
我建议安装在浅层上,因为子组件可以
深度嵌套,需要多个.dive调用;但是,如果
您知道“EditCard”的子组件只是简单的JSX元素,
那就好了
*/
包装器=mount();
});
它(“当提交的表单带有空的“#Name”字段时,不应调用‘updateUser’,()=>{
/*
我不确定模拟“null”对这个输入有什么作用,但假设
输入是必需的,您至少应该传递一个字符串值——假设
“#Name”输入类型为“text”|“password”|“email”=>字符串和
不是数字。在相关注释中,如果需要,只需删除此项即可
编写代码,因为它对测试没有多大作用。
*/
//find('#Name').simulate('change',{target:{value:'}});
/*
我假设这会模拟表单提交。不幸的是,
按提交按钮不起作用。相反,你必须
模拟一个表单提交。这是一个酶的限制和最后一个I
已检查但尚未/无法修复。
*/
wrapper.find('form').simulate('submit');
/*
此后提交时,它不应调用jest.fn()“updateUser”
“#Name”为空。请注意,我们引用的是“updateUser”——笑话fn
上面定义了——而不是wrapper.prop fn。
*/ 
expect(updateUser).not.tohavebeencall();
});
//包括其他测试。。。
});

下面是一个工作示例(单击
Tests
选项卡以运行测试):


非常感谢!我想关键点是在
defaultProps
之外定义函数,这样我就不必从props获取函数来检查它们被调用了多少次,因为使用
shall
是不可行的。我想使用
shall
时我无法从props获取函数。我尝试了
mount
但是如果我必须坚持使用
shallow
,我必须在
defaultProps
之外定义它们。