除了你的方式之外,你几乎没有任何变化spyOn。当您使用的间谍,你有两个选择:spyOn在App.prototype或组件component.instance()。
const spy = jest.spyOn(Class.prototype, "method")
在类原型上附加间谍和渲染(浅渲染)实例的顺序很重要。
const spy = jest.spyOn(App.prototype, "myClickFn");
const instance = shallow(<App />);
在App.prototype第一行位有你需要的东西,使事情的工作。JavaScriptclass没有任何方法,除非您使用 实例化它new MyClass(),或者您使用MyClass.prototype. 对于您的特定问题,您只需要监视App.prototype方法myClickFn。
jest.spyOn(component.instance(), "方法")
const component = shallow(<App />);
const spy = jest.spyOn(component.instance(), "myClickFn");
此方法需要 a 的shallow/render/mount实例React.Component可用。本质spyOn上只是在寻找可以劫持并推入jest.fn(). 它可能是:
一个平原object:
const obj = {a: x => (true)};
const spy = jest.spyOn(obj, "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.
或者React.Component instance:
const component = shallow(<App />);
/*
component.instance()
-> {myClickFn: f(), render: f(), ...etc}
*/
const spy = jest.spyOn(component.instance(), "myClickFn");
或者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.
我已经使用并看到了这两种方法。当我有一个beforeEach()orbeforeAll()块时,我可能会采用第一种方法。如果我只需要一个快速间谍,我会使用第二个。只需注意附加间谍的顺序即可。
编辑:如果你想检查你的副作用,myClickFn你可以在单独的测试中调用它。
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");
*/
编辑:这是使用功能组件的示例。请记住,在您的功能组件范围内的任何方法都不可用于监视。您将监视传递到您的功能组件中的功能props并测试它们的调用。本实施例中探讨了使用的jest.fn(),而不是jest.spyOn,这两者的共享模拟函数API。虽然它没有回答最初的问题,但它仍然提供了对其他技术的见解,这些技术可以适用于与问题间接相关的案例。
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*/);