Jest与Enzyme,为什么`toHaveBeenCalled`在我的React组件测试中没有触发?

问题描述 投票:0回答:1

我正在React应用程序中进行一个单元测试,以验证一个传递进来的prop函数是否被基于另一个props值而有条件地调用。我在我的应用程序中利用TypescriptEnzymeJest,并使用了一个名为 "HaveBeenCalled "的测试。Root 围绕我正在测试的组件的包装器来注入Redux存储(如果需要的话,还可以覆盖初始状态)。

import { mount, ReactWrapper } from "enzyme";
import React from "react";
import Login from "src/components/auth/Login";
import Root from "src/Root";

let wrapped: ReactWrapper;

let defaultProps = {
  signIn: jest.fn(),
  token: null,
};

beforeEach(() => {
  wrapped = mount(
    <Root>
      <Login {...defaultProps} />
    </Root>
  );
});

describe("on mount", () => {
  describe("if no token is supplied to the props", () => {
    it("will call the props.signIn() function", () => {
      expect(defaultProps.signIn).toHaveBeenCalled();
    });
  });
});

当我运行测试时 toHaveBeenCalled() (以及 toBeCalled(),都试过了)都没有注册任何调用。然而,我已经提供了一个 console.log 语句,该语句将被触发在与 signIn() 功能的生命。

import React from 'react';
import { AuthState, JWT } from "src/components/auth/types";
import { signIn } from "src/redux/auth";

interface Props {
  signIn: () => Promise<void>;
  token: null | JWT;
}

class Login extends React.Component<Props> {
  /**
   * Sign the user in on mount
   */
  public componentDidMount(): void {
    if (!this.props.token) {
      console.log("GETTING HERE");
      this.props.signIn();
    }
  }

  public render(): JSX.Elemeent {
    // ... More code
  }
}

const mapStateToProps = (state: AuthState) => {
  return {
    token: state.auth.token;
  };
};

export default connect(mapStateToProps, { signIn })(Login);

我翻了好几篇相关的帖子文章,但都是不同的配置,比如遍历酶来获得直接道具,或者利用 spyOn,都失败了。

我唯一能想到的不同之处是我的包装上的 Login 组成部分与 Root但考虑到我可以看到 console.log 被触发,这似乎是一个完整的射击在黑暗中。

谁能告诉我,我在这里做错了什么?

reactjs typescript testing enzyme jest
1个回答
1
投票

你要等组件挂载,所以。

it("will call the props.signIn() function", (done) => {
  setImmediate(() => {
    expect(defaultProps.signIn).toHaveBeenCalled();
    done()
  });
});

0
投票

结果是我忘了把覆盖的地方通过... mapDispatchToPropsmapStateToPropsconnect 函数。这导致我的传入的 signIn 函数来覆盖 signIn 文件中导入的动作。更新与 ownProps 并有条件地利用传入的值来解决这个问题。

const mapStateToProps = (state: AuthState, ownProps: Props) => {
  return {
    token: ownProps.token || state.auth.token;
  };
};

const mapDispatchToProps = (dispatch: ThunkDispatch<{}, {}, any>, ownProps: Props) => {
  return {
    signIn: ownProps.signIn || (() => { return dispatch(signIn()) })
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(Login);
© www.soinside.com 2019 - 2024. All rights reserved.