我正在尝试用Jest测试React组件的状态 . 在ComponentDidUpdate上,如果有人登录并使用用户名更新state.user,它将在服务器上获取用户名 . 如果没有用户登录,则会将state.pleaseLogin切换为true .
import React from "react";
import "./Header.css";
import "whatwg-fetch";
import LoggedInNav from "./LoggedInNav";
import LoggedOutNav from "./LoggedOutNav";
import urls from "../../urls";
import getUser from "../fetch/getUser";
export default class Header extends React.Component {
constructor(props) {
super(props);
this.state = {
user: null,
pleaseLogin: false
};
this.handleGetUser = this.handleGetUser.bind(this);
}
handleGetUser() {
getUser().then(res => {
if (res.hasOwnProperty("username")) {
this.setState({
user: res.username
});
} else {
this.setState({
pleaseLogin: true
});
}
});
}
componentDidMount() {
this.handleGetUser();
}
render() {
let nav;
if (this.state.user) {
nav = <LoggedInNav user={this.state.user} />;
} else if (this.state.pleaseLogin) {
nav = <LoggedOutNav />;
} else {
nav = null;
}
return (
<header className="app-header">
<h1 className="header-brand">Watchers</h1>
{nav}
</header>
);
}
}
以下是getUser()的代码,用于在服务器上获取用户名:
export default () => {
return fetch(`${BASE_URL}/api/user/user_data`, {
credentials: "include"
})
.then(res => res.json())
.catch(error => {
console.log(error);
return error;
});
};
我手动模拟了API调用 . 该文件名为'getUser.js',位于原始'getUser.js'旁边的 mocks 文件夹中,如下所示:
export default () => {
return Promise.resolve({
username: 'Username'
})
}
然后测试:
import React, { Component } from "react";
import Enzyme, { shallow, mount } from "enzyme";
import Adapter from "enzyme-adapter-react-16";
import Header from "../react/components/Header";
import getUser from "../react/fetch/getUser";
Enzyme.configure({ adapter: new Adapter() });
jest.mock("../react/fetch/getUser");
const wrapper = mount(<Header />);
describe("<Header/>", () => {
describe("component class", () => {
it("should update state.user after componentDidMount()", () => {
return getUser().then(() => {
expect(wrapper.state()).toEqual({
user: "Username",
pleaseLogin: false
});
});
});
});
});
测试通过,状态发生了变化,state.user现在等于“Username” . 如果我更改我的模拟模块并使其返回一个空对象,它也可以正常工作,并且state.pleaseLogin切换为true . 但是我必须手动测试这两种情况 . 我尝试使用jest.mock('... module',()=> {})直接在我的测试文件中模拟这两个不同的实现,并使用jest.doMock('... module',()=> {})但是当我运行测试时状态不会更新;虽然它与手动模拟 . 我不确定问题的来源,也许这与异步性或在Jest中嘲笑有关?
1 回答
我找到了两种不同的测试方法 .
由于模拟模块仅包含一个函数,因此手动模拟可能不是最佳解决方案 . 不过这是我写测试的方式:
1.在 mocks 文件夹中手动模拟
Test
2.创建 mock function 以在测试代码中使用
Test
一些值得注意的事情:
我试图在测试中使用mock和doMock失败 . 它可能与此问题有关:https://github.com/facebook/jest/issues/2582
但是,mockImplementationOnce()将在此测试中引发错误
必须在模拟之后调用酶shallow()或mount()才能使用该实现 . 否则我们得到'TypeError:无法读取属性'然后'未定义'
承诺需要退回 . 如果没有'return',那么'then'中的期望将被跳过,因为我们不等待异步调用返回 .
您可以查看以下链接,了解如果省略return,会发生什么:https://github.com/facebook/jest/issues/1924