首页 > 解决方案 > Not getting expected result from .toHaveBeenCalledTimes() in react-testing-library

问题描述

Anyhow, trying to test if a function has been called after its fired. The fireEvent is working as I get a console.log from that function. But the .toHaveBeenCalledTimes(1) returns 0. What have i missed?

If I have the handleLoginSubmit function in the parent and pass it as a prop down to the child and in the test everything passes. But if it's in the same component it fails. Using typescript if that has any meaning.

This is tested

import React, { FC } from 'react';

type Event = React.FormEvent<HTMLFormElement>;

interface Login {
  handleLoginSubmit?: (event: Event) => React.ReactNode;
}

const Login: FC<Login> = () => {
  const handleLoginSubmit = (_event: Event) => {
    console.log('Firing' ); // This is logged
  };

  return (
    <form data-testid='form' onSubmit={(event) => handleLoginSubmit(event)}>
      <input data-testid='email'/>
      <input data-testid='password'/>
      <button data-testid='login-button'>login</button>
    </form>
  );
};

export default Login;

My test for submiting

  it('should handle ClickEvents', () => {

    const handleLoginSubmit = jest.fn();

    const { getByTestId } = render(<Login/>);

    expect(getByTestId('login-button')).toBeTruthy();

    fireEvent.submit(getByTestId('form'));

    expect(handleLoginSubmit).toHaveBeenCalledTimes(1);

  });

Error message

 ● Login page › should handle ClickEvents

    expect(jest.fn()).toHaveBeenCalledTimes(expected)

    Expected number of calls: 1
    Received number of calls: 0

      32 |     fireEvent.submit(getByTestId('form'));
      33 | 
    > 34 |     expect(handleLoginSubmit).toHaveBeenCalledTimes(1);
         |                               ^
      35 | 
      36 |   });
      37 | });

      at Object.it (__tests__/components/Login.test.tsx:34:31)

标签: reactjsunit-testingjestjsreact-testing-library

解决方案


您不能断言是否handleLoginSubmit要直接调用该函数。Login因为它是在SFC的私有范围内定义的。您无法模拟或监视此功能,因为您无法访问它。因此,您需要间接测试它。由于您console.log在此功能中使用,我们可以窥探console.log. 如果它已被调用,则表示该handleLoginSubmit函数已被调用。

例如

index.tsx

import React, { FC } from "react";

type Event = React.FormEvent<HTMLFormElement>;

interface Login {
  handleLoginSubmit?: (event: Event) => React.ReactNode;
}

const Login: FC<Login> = () => {
  const handleLoginSubmit = (_event: Event) => {
    console.log("Firing");
  };

  return (
    <form data-testid="form" onSubmit={event => handleLoginSubmit(event)}>
      <input data-testid="email" />
      <input data-testid="password" />
      <button data-testid="login-button">login</button>
    </form>
  );
};

export default Login;

index.spec.tsx

import { render, fireEvent } from "@testing-library/react";
import Login from "./";
import React from "react";

it("should handle ClickEvents", () => {
  const logSpy = jest.spyOn(console, "log");
  const { getByTestId } = render(<Login />);
  expect(getByTestId("login-button")).toBeTruthy();
  fireEvent.submit(getByTestId("form"));
  expect(logSpy).toHaveBeenCalledTimes(1);
});

覆盖率 100% 的单元测试结果:

 PASS  src/stackoverflow/59162138/index.spec.tsx
  ✓ should handle ClickEvents (42ms)

  console.log node_modules/jest-mock/build/index.js:860
    Firing

-----------|----------|----------|----------|----------|-------------------|
File       |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
-----------|----------|----------|----------|----------|-------------------|
All files  |      100 |      100 |      100 |      100 |                   |
 index.tsx |      100 |      100 |      100 |      100 |                   |
-----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        3.987s, estimated 9s

源代码:https ://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/59162138


推荐阅读