Jest在JSX单元测试中Mock组件遇报错及取值问题求助
Hey there! Let's work through your Jest test issues one by one to get things sorted out.
Fixing the jest.fn() value must be a mock function or spy Error
This error pops up because you're trying to use toBeCalledWith() (or its negation) on something that isn't a mock function or spy—in your case, the plain object {"a": "2"}.
Here's what you need to do:
- Double-check that the value you're passing to
expect()is actually a mock or spy. For example, if you're asserting a component method was called, you first need to create a spy on that method usingjest.spyOn(). - Avoid accidentally passing plain objects or component instances to
expect()when you mean to target a method.
Example of what not to do:
// ❌ This will throw the error because obj isn't a mock function const obj = { a: "2" }; expect(obj).toBeCalledWith("someArgument");
Correct approach for component methods:
// ✅ Create a spy on the component's prototype method first const componentWillMountSpy = jest.spyOn(YourComponent.prototype, "componentWillMount"); // Render your component... expect(componentWillMountSpy).toBeCalled(); // Now this works!
Mocking componentWillMount to Get the Correct showName Value
If you're consistently getting "No Name" after mocking componentWillMount, there are a few common pitfalls to fix:
Ensure Your Mock Binds to the Component Instance
When mocking the lifecycle method, use a regularfunction(not an arrow function) sothisrefers to the component instance. Arrow functions won't bind to the component'sthis, so settingthis.showNamewon't update the instance's value.Example of a working mock:
import YourComponent from "../dist/container/index"; import { shallow } from "enzyme"; // Assuming you're using Enzyme for rendering describe("YourComponent", () => { it("sets showName correctly via componentWillMount", () => { // Create a spy and mock the implementation const mockMount = jest.spyOn(YourComponent.prototype, "componentWillMount"); mockMount.mockImplementation(function() { this.showName = "My Custom Name"; // `this` points to the component instance here }); // Render the component (this triggers componentWillMount) const wrapper = shallow(<YourComponent />); // Check the showName value on the instance expect(wrapper.instance().showName).toBe("My Custom Name"); // Verify the lifecycle method was called expect(mockMount).toHaveBeenCalled(); // Clean up the spy after the test mockMount.mockRestore(); }); });Mock Before Rendering the Component
componentWillMountruns immediately when the component mounts, so your mock needs to be set up before you render the component. If you render first and mock later, the original lifecycle method will run instead of your mock.Check for Default Values Overriding Your Mock
If "No Name" is the default value ofshowNameset elsewhere (like the constructor), make sure your mock explicitly overwrites it. If your mock doesn't setthis.showNameat all, the default will stick around.
Quick Recap
- For the spy/mock error: Always assert against a
jest.fn()orjest.spyOn()result, not plain objects. - For the
showNameissue: Use regular functions in your mock to preservethisbinding, set up the mock before rendering, and ensure your mock explicitly sets theshowNamevalue.
内容的提问来源于stack exchange,提问作者user3686652

