【问题标题】:Jest automock not applied to a moduleJest automock 未应用于模块
【发布时间】:2019-08-29 09:44:47
【问题描述】:

我在为我的模块运行 Jest 测试时遇到了麻烦 - 我有一个简单的入口点类:

import { Callback, CloudFrontRequestEvent, Context, Handler } from "aws-lambda";

import { CloudFrontHandler } from "./CloudFrontHandler";
import { OriginClient } from "./OriginClient";
import { ResponseRenderer } from "./ResponseRenderer";
import { TemplateRenderer } from "./TemplateRenderer";

export class LambdaHandler {
    private readonly renderer: TemplateRenderer;

    constructor(renderer: TemplateRenderer) {
        this.renderer = renderer;
    }

    public handle: Handler = (event: CloudFrontRequestEvent, _: Context, callback: Callback): void => {
        console.log(new CloudFrontHandler(null, null)); // <- just an empty object here! CloudFrontHandler {}
        console.log(new OriginClient(null)); // <- properly mocked
        console.log(new ResponseRenderer(null, null)); // <- properly mocked
        new CloudFrontHandler(
            new OriginClient(event.Records[0].cf.request),
            new ResponseRenderer(callback, this.renderer),
        )
            .handle(); // <- because CloudFrontHandler is not mocked, an error occurs here
    }
}

无论出于何种原因,CloudFrontHandler 类都不会被模拟(OriginClientResponseRenderer 被正确地自动模拟)。以下是我的测试课:

import "jest";
import { Callback, CloudFrontRequest, CloudFrontRequestEvent } from "aws-lambda";
import { mocked } from "ts-jest/utils";
import { LambdaHandler, TemplateRenderer } from "../../../main/nodejs";

import { CloudFrontHandler } from "../../../main/nodejs/edge/CloudFrontHandler";
import { OriginClient } from "../../../main/nodejs/edge/OriginClient";
import { ResponseRenderer } from "../../../main/nodejs/edge/ResponseRenderer";

jest.mock("../../../main/nodejs/edge/CloudFrontHandler");
jest.mock("../../../main/nodejs/edge/OriginClient");
jest.mock("../../../main/nodejs/edge/ResponseRenderer");

const MockedCloudFrontHandler = mocked(CloudFrontHandler);
const MockedOriginClient = mocked(OriginClient);
const MockedResponseRenderer = mocked(ResponseRenderer);

describe("LambdaHandler", (): void => {
        it("should handle CloudFront request", (): void => {
                const templateRenderer: TemplateRenderer = {} as TemplateRenderer;
                const callback: Callback = jest.fn() as Callback;
                const request: CloudFrontRequest = {} as CloudFrontRequest;
                const event: CloudFrontRequestEvent = {
                    Records: [
                        {
                            cf: {
                                request: request,
                            },
                        },
                    ],
                } as CloudFrontRequestEvent;

                let handler: LambdaHandler = new LambdaHandler(templateRenderer);
                handler.handle(event, null, callback)
                // todo

                expect(MockedCloudFrontHandler).toHaveBeenCalledTimes(1);
                expect(MockedOriginClient).toHaveBeenCalledTimes(1);
                expect(MockedResponseRenderer).toHaveBeenCalledTimes(1);
        });
});

(我将源文件和测试文件分开保存,因此所有这些 src/main src/test 路径)

为什么 Jest 不会模拟这个模块类?

-编辑-

错误信息是:

TypeError: (intermediate value).handle is not a function

【问题讨论】:

  • 你使用的是什么版本的 NodeJS?我相信我可能已经看到了同样的问题here,但仅限于 NodeJS 11.x。旧版本的 NodeJS 工作正常。
  • 我使用的是 11.0.0。
  • 用 10.13 和 8.15 尝试过 - 行为相同。
  • @10101010 你可能只是指出了根本原因——它是一个箭头函数,所以在 TypeScript 中它被转换为 JavaScript 作为构造函数中分配的属性。我会检查一下。

标签: typescript mocking jestjs


【解决方案1】:

我的问题下的评论指出了根本原因 - 这里的问题是,CloudFrontHandler.handle 是一个箭头函数,TypeScript 将其转换为构造函数中分配的属性。由于构造函数是自动模拟的,因此未分配函数。为.handle() 方法创建手动模拟可以解决问题。

【讨论】:

    猜你喜欢
    • 2021-03-02
    • 2020-08-07
    • 1970-01-01
    • 1970-01-01
    • 2019-04-01
    • 2021-02-04
    • 2019-08-17
    • 2017-10-18
    • 2022-07-10
    相关资源
    最近更新 更多