instance()。setState函数不适用于单元测试

时间:2019-07-18 11:58:32

标签: react-native jestjs enzyme

我有一个单元测试来检查页面是否创建良好。但是我有一个问题。我在Categories ID PARENT_ID NAME 1 0 Shopping 2 1 Health Business_Categories ID BUSINESS_ID CATEGORY_ID 1 1 1 2 1 2 方法上为用户定义了一个空数组,然后为在constructor方法上调用的方法分配了一个数组。当我自己在设备上进行测试时,一切正常。但是开玩笑的测试会由于用户数组未定义而引发错误(我猜这是不可能的,因为我在构造函数方法中将其定义为[])。

Users.js的一部分;

componentDidMount

Users.spec.js;

export default class Users extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      users: [],
      firmId: 0,
      key: 0,
      isLoading: true,
    };
  }

componentDidMount() {
    this.getData();
}

getData() {
    return fetch("censored url" + this.state.firmId)
      .then(response => response.json())
      .then(responseJson => {
        this.setState(
          {
            users: responseJson.users,
            isLoading: false
          },
          function() {}
        );
      })
      .catch(error => {
        console.error(error);
      });
  }

我指出了带有THROWS ERROR注释的引发错误的测试。

cmd错误;

// other imports
import { users } from "../../jest/mock-data";

describe("<Users>", () => {
  function func(){
    return "2"
  }
  const navigation = { navigate: jest.fn(), getParam: func };

  it('fetches data from server when server returns a successful response', done => { // 1
    const mockSuccessResponse = users;
    const mockJsonPromise = Promise.resolve(mockSuccessResponse); // 2
    const mockFetchPromise = Promise.resolve({ // 3
      json: () => mockJsonPromise,
    });
    jest.spyOn(global, 'fetch').mockImplementation(() => mockFetchPromise); // 4

    const component = shallow(<Users navigation={navigation}/>);    // 5

    component.instance().setState({
      users: [],
      isLoading: false
    });

    expect(global.fetch).toHaveBeenCalledTimes(2); //success
    expect(global.fetch).toHaveBeenCalledWith("censored url/2"); //success

    process.nextTick(() => { // 6
      expect(component.state()).toEqual({
        users: users,
        isLoading: false,
        firmId: "2",
        key: "2"
      });  // THROWS ERROR

      global.fetch.mockClear(); // 7
      done(); // 8
    });
  });
 }); 

我猜 ● <Users> › fetches data from server when server returns a successful response expect(received).toEqual(expected) // deep equality - Expected + Received Object { "firmId": "2", "isLoading": false, "key": "2", - "users": Array [ - Object { - "createdAt": 1547939031000, - "email": "test@firm.com", - "firstName": "Test", - "id": 5, - "lastName": "User", - "phone": "45454545454", - "status": null, - "updatedAt": 1547939031000, - }, - ], + "users": undefined, } 48 | 49 | process.nextTick(() => { // 6 > 50 | expect(component.state()).toEqual({ | ^ 51 | users: users, 52 | isLoading: false, 53 | firmId: "2", 效果不佳,但我不确定。如果您知道答案并能帮助我解决该问题,我将感到很高兴。

编辑:我试图在setState函数中添加一个包含在测试文件中的新变量。当我对它进行测试时,它会很好地工作。因此,它只是不适用于用户变量。

2 个答案:

答案 0 :(得分:0)

我解决了这个问题。问题是关于我的嘲弄方式。我是新手,不擅长嘲笑。我仍然不确定为什么,但是生命周期方法将用户变量定义为未定义。在this stackoverflow question's answer上,我看到了一种在浅层函数运行时阻止生命周期运行的方法。因此,我使用了该方法,而不是模拟提取,并且阻塞了的生命周期方法调用了提取函数(我在项目中将其命名为getData())。并向用户变量声明了模拟数据。

这是如何在浅层函数中阻止生命周期方法;

const navigation = { navigate: jest.fn(), getParam: jest.fn() };
const component = shallow(<Users navigation={navigation}/>, { disableLifecycleMethods: true });    // 5

导航部分即将模拟反应导航

答案 1 :(得分:0)

设置状态后,我们需要在实例上调用update,以便强制重新渲染,并在组件状态中更新值。

    component.instance().setState({
      users: [],
      isLoading: false
    });
    // Add this line
    component.instance().update();