我是javascript新手,请开玩笑。我想模拟一个将作为上下文值传递的函数。我能够传递模拟函数,并且无法看到模拟函数已触发,但是当我尝试检查模拟以断言结果时。即时通讯出现错误,附在下面。
这是我要测试的课程:
class Login extends Component {
constructor(props) {
super(props);
this.state = {
authInProgress: true,
authSuccess: false
};
}
componentDidMount() {
if (this.context.isAuthenticated) {
this.setState({
authInProgress: false,
authSuccess: true
});
} else {
isUserLoggedIn().then((response) => {
this.context.logIn();
this.setState({
authInProgress: false,
authSuccess: true
});
}).catch((err) => {
console.log(err);
});
}
}
render() {
if (this.state.authInProgress) {
return <div>Rendering login</div>;
} else if (this.state.authSuccess) {
return <Redirect to={ROOT}/>;
}
}
}
Login.contextType = Context;
export default Login;
这是我的测试
it("When user is logged In, then update the context and redirect to ROOT.", () => {
const resp = {
data: {
responseCode: 600
}
};
isUserLoggedIn.mockResolvedValue(resp);
const mockLogIn = jest.fn(() => console.log("im hit"));
act(() => {
render(
<MemoryRouter>
<Context.Provider value={{isAuthenticated: false, logIn: mockLogIn}}>
<Login/>
</Context.Provider>
</MemoryRouter>
, container);
});
expect(mockLogIn.mock.calls.length).toBe(1);
});
这是测试结果:
console.log src/__tests__/auth/components/Login.test.jsx:62
im hit
Error: expect(received).toBe(expected) // Object.is equality
Expected: 1
Received: 0
<Click to see difference>
我看到模拟功能被触发了。但模拟的状态不会更新。我在这里做错了什么?
与范围有关吗?我尝试在行为块之外调用模拟函数,并将状态更新为模拟。当同一调用在该块内发生时,将无法正常工作。
答案 0 :(得分:1)
那么异步是这里的问题。我开始使用很棒的react-testing-library并添加了等待测试的时间。然后它按预期工作。
现在我的测试看起来像这样
it("When the user's session is still active (auth tokens are valid), then refresh the tokens and the user is redirected to root.", async () => {
const resp = {
data: {
responseCode: 600
}
};
isUserLoggedIn.mockResolvedValue(resp);
refreshAuthData.mockImplementation();
const mockLogin = jest.fn();
const {history} = renderWithContextAndRouter(
<Login/>, {
route: "/login",
context: {
isAuthenticated: false,
logIn: mockLogin
}
}
);
await waitFor(() => {
expect(history.location.pathname).toBe("/");
expect(mockLogin.mock.calls.length).toBe(1);
});
});
renderWithContextAndRouter
是一个HOC,可注入我的上下文和路由。我的实际测试甚至没有此验证,因为这些只是实现细节。这只是为了帮助一些初学者:)