【问题标题】:Cannot spy on mocked functions of a class using a manual mock无法使用手动模拟监视类的模拟函数
【发布时间】:2020-10-03 18:03:56
【问题描述】:

注意:我创建了一个完整配对的 Github 存储库,您可以自己下载和结帐here

我正在尝试使用与文件直接相邻的文件夹 __mocks__ 中的手动模拟来模拟模块中的非默认导出类。这工作正常,我可以让模拟在我的测试中正确加载。但是,如果我按照here in the docs 的描述导出模拟函数,它似乎实际上并没有给我一个对模拟类在测试中调用的函数的引用。这意味着当我打电话时

expect(getAppDetailMock).toHaveBeenCalledTimes(1);

它失败了,因为它根本没有被调用。

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

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

我的怀疑是它与类本身有关,最终得到一个新版本的函数,而不是我要导入的同一个引用......我这么说是因为我做了完全相同的模式来模拟在我的node_modules 中取出一个包,它不是 一个类,它工作得非常好。

尽管您可以查看完整的代码示例here on github,但为了清楚起见,我已经复制了下面的文件。关于为什么这不符合我的预期的任何想法?

// api/__mocks__/clients.ts

export const getAppDetailMock = jest.fn();
export const AppsClient = jest.fn().mockImplementation(() => {
  return {
    getAppDetail: getAppDetailMock,
  };
});

// App.test.js

import React from "react";
import {
  render,
  screen,
  waitForElementToBeRemoved,
} from "@testing-library/react";
import App from "./App";
import { getAppDetailMock } from "./api/__mocks__/clients";

jest.mock("./api/clients");

describe("<App /> ", () => {
  beforeEach(() => {
    getAppDetailMock.mockReset();
  });
  test("Should show not found message if app does not exist", async () => {
    const appId = "8500f5dd-8b41-4cb8-95fa-246b1f25855b";
    getAppDetailMock.mockResolvedValue(null);
    render(<App appId={appId} />);
    await waitForElementToBeRemoved(() => screen.getByText("Loading"));
    expect(getAppDetailMock).toHaveBeenCalledTimes(1);
    expect(getAppDetailMock).toHaveBeenCalledWith(appId);
    expect(screen.getByText(`App not found found`)).toBeInTheDocument();
  });
  test("Should show not found message if app does not exist", async () => {
    const appId = "8500f5dd-8b41-4cb8-95fa-246b1f25855b";
    getAppDetailMock.mockResolvedValue({ appId });
    render(<App appId={appId} />);
    await waitForElementToBeRemoved(() => screen.getByText("Loading"));
    expect(getAppDetailMock).toHaveBeenCalledTimes(1);
    expect(getAppDetailMock).toHaveBeenCalledWith(appId);
    expect(
      screen.getByText(`App found with id '${appId}'`)
    ).toBeInTheDocument();
  });
});

// App.tsx

import React, { useState, useEffect } from "react";
import "./App.css";

import { AppsClient, AppDetailDto } from "./api/clients";

type AppProps = {
  appId: string;
};

const App: React.FC<AppProps> = ({ appId }) => {
  const [hasLoaded, setHasLoaded] = useState(false);
  const [appDetail, setAppDetail] = useState<AppDetailDto | null>(null);

  useEffect(() => {
    const getAppDetail = async (appId: string) => {
      try {
        setHasLoaded(false);
        const result = await new AppsClient().getAppDetail(appId);
        setAppDetail(result);
        setHasLoaded(true);
      } catch (error) {}
    };
    if (!hasLoaded) {
      getAppDetail(appId);
    }
  }, [appId, hasLoaded]);

  if (!hasLoaded) {
    return <>Loading</>;
  } else if (!appDetail) {
    return <>App not found found</>;
  }

  return <>App found with id '{appDetail.appId}'</>;
};

export default App;

// api/clients.ts

import { BaseClient } from "./baseClient";

export interface AppDetailDto {
  appId: string;
}

export class AppsClient extends BaseClient {
  getAppDetail(appId: string): Promise<AppDetailDto> {
    return Promise.resolve({ appId });
  }
}

【问题讨论】:

  • 我猜它必须像expect(AppsClient. getAppDetail).toHaveBeenCalledTimes(1);

标签: reactjs typescript jestjs


【解决方案1】:

尝试检查您的getAppDetail 是否已被调用。

所以更像是: expect(getAppDetail).toHaveBeenCalledTimes(1);

或者,如果可以的话,拉入整个模拟组件并检查它的特定 getAppDetail 是否已被调用,例如: expect(AppsClient.getAppDetail).toHaveBeenCalledTimes(1);

您的怀疑可能是正确的......事实上,您正在导入 getAppDetailMock 的单独实例,它的实例不会被调用,因为它是与 AppsClient.getAppDetail 无关的单独导入模拟。

【讨论】:

    【解决方案2】:

    尝试使用 @ts-ignore 从 ./api/clients 直接导入

    // @ts-ignore
    import { getAppDetailMock } from "./api/clients";
    

    import * as Clients from './api/clients';
    import * as ClientsMock from './api/__mocks__/clients';
    
    jest.mock("./api/clients");
    
    const {
      getAppDetailMock
    } = (Clients as unknown) as typeof ClientsMock;
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-07
      • 1970-01-01
      • 1970-01-01
      • 2020-10-10
      相关资源
      最近更新 更多