当前位置: 首页 > 知识库问答 >
问题:

如何使用TypeScript部分测试AWS Lambda?

邬阳
2023-03-14

非常类似于使用部分形状对typescript进行单元测试,但我无法理解为什么部分类型被视为与完整版本不兼容。

我有一个单元测试,如果AWS lambda事件中的body无效,则检查lambda是否返回400。为了避免给我的同事制造噪音,我不想创建具有完整APIGatewayProxyEvent所有属性的invalidEvent。因此,使用部分

  it("should return 400 when request event is invalid", async () => {
    const invalidEvent: Partial<APIGatewayProxyEvent> = {
      body: JSON.stringify({ foo: "bar" }),
    };
    const { statusCode } = await handler(invalidEvent);
    expect(statusCode).toBe(400);
  });

const{statusCode}=wait处理程序(invalidEvent) 行编译失败,原因是:

Argument of type 'Partial<APIGatewayProxyEvent>' is not assignable to parameter of type 'APIGatewayProxyEvent'.
  Types of property 'body' are incompatible.
    Type 'string | null | undefined' is not assignable to type 'string | null'.
      Type 'undefined' is not assignable to type 'string | null'.ts(2345)

我理解APIGatewayProxyEventbody可以是string | null(从类型上看),但是string | null | undefined是从哪里来的?为什么我的正文(字符串)不是APIGatewayProxyEvent的有效正文

如何使用TypeScript部分测试AWS Lambda?

我可以使用作为来做类型断言,但是我发现部分更显式。下面的代码工作,虽然:

    const invalidEvent = { body: JSON.stringify({ foo: "bar" }) } as APIGatewayProxyEvent;
  type TestingEventWithBody = Omit<Partial<APIGatewayProxyEvent>, "body"> & Pick<APIGatewayProxyEvent, "body">;

  it("should return 400 when request event is invalid", async () => {
    const invalidEvent: TestingEventWithBody = { body: JSON.stringify({ foo: "bar" }) };
    const { statusCode } = await handler(invalidEvent);
    expect(statusCode).toBe(400);
  });

在以下情况下失败:

Argument of type 'TestingEventWithBody' is not assignable to parameter of type 'APIGatewayProxyEvent'.
  Types of property 'headers' are incompatible.
    Type 'APIGatewayProxyEventHeaders | undefined' is not assignable to type 'APIGatewayProxyEventHeaders'.
      Type 'undefined' is not assignable to type 'APIGatewayProxyEventHeaders'.ts(2345)

共有2个答案

松霖
2023-03-14

这里的问题是,分部类型将所有对象属性转换为可选:

type MyObj = { myKey: string | null };

type MyPartialObj = Partial<MyObj>;
// MyPartialObj is: { myKey?: string | null | undefined }

在类型MyObj中,myKey类型为string | null。当我们将其转换为MyPartialObj时,myKey类型成为可选的,因此可能是未定义的。所以现在它的类型是string | null | undefined

您的APIGatewayProxyEvent类型要求bodystring | null,但是由于您将其设置为部分,因此您所说的body也可能是未定义的。是的,您已经定义了它,但是您从未进行过类型缩小以验证它确实是一个字符串。因此,TypeScript必须关闭的所有类型都是您指定的类型,这也是部分类型
更新:扩展@jornsharpe在评论中所说的内容。我以前的解决方案似乎不起作用,它只是将错误推送到APIGatewayProxyEvent中的下一个属性。看看他们的答案。问题是您试图模拟数据的一部分,而该类型希望所有数据都存在。创建一个对象,使每个属性的值都最小,而不是试图伪造它,这可能是最简单的。您可以将用作,但这首先破坏了使用类型系统的全部意义
前面的答案:一个解决方案可能是使所有值都是可选的,除了body

const invalidEvent: Omit<Partial<APIGatewayProxyEvent>, 'body'> & Pick<APIGatewayProxyEvent, 'body'> = {
    body: JSON.stringify({ foo: "bar" }),
};

另外,避免像瘟疫一样使用作为x,除非你完全确定自己在做什么。

袁晟
2023-03-14

我无法理解为什么部分类型被视为与完整版本不兼容

从根本上说,这是不可避免的-您从要求body属性为string | null的内容开始,并创建了要求较弱的string | null | undefined的内容。在本例中,您确实提供了正文,但这并不重要,因为处理程序仅通过部分代码查看无效事件

在不拥有处理程序API的情况下,实际上只有三种选择,没有一种是理想的:

  1. 实际提供完整的APIGatewayProxyEvent(有关此操作的快捷方式,请参见末尾)

使用部分代码通常只是选项2中的一个步骤,使用:

const thing: Partial<Thing> = { ... };
whatever(thing as Thing);

而不是:

const thing = { ... } as Thing;
whatever(thing);

如果您拥有处理程序的API,最好的方法是应用接口隔离原则,并具体说明它实际需要做什么工作。如果只是body,例如:

type HandlerEvent = Pick<APIGatewayProxyEvent, "body">;

function handler(event: HandlerEvent) { ... } 

完整的APIGatewayProxyEvent仍然是处理程序的有效参数,因为它确实有一个主体(而且它还有其他属性这一事实与此无关,它们无法通过HandlerEvent访问)。这还可以作为内置文档,说明您从完整对象中实际消费了什么。

在您的测试中,您现在可以创建较小的对象:

it("should return 400 when request event is invalid", async () => {
  const invalidEvent: HandlerEvent = { body: JSON.stringify({ foo: "bar" }) };
  const { statusCode } = await handler(invalidEvent);
  expect(statusCode).toBe(400);
});

作为奖励,如果稍后发现您需要访问处理程序中的更多事件属性,您可以更新类型:

type HandlerEvent = Pick<APIGatewayProxyEvent, "body" | "headers">;

你需要更新测试数据以考虑到这一点,你会在任何地方得到错误。这不会发生在const无效事件={...}作为APIGatewayProxy事件;,您必须通过查看哪些测试在运行时失败来跟踪更改。

我在选项1中看到的另一个快捷方式是将函数包装在部分周围,提供合理的默认值:

function createTestData(overrides: Partial<APIGatewayProxyEvent>): APIGatewayProxyEvent {
  return {
    body: null,
    headers: {},
    // etc.
    ...overrides,
  };
}

it("should return 400 when request event is invalid", async () => {
  const invalidEvent = createTestData({ body: JSON.stringify({ foo: "bar" }) });
  const { statusCode } = await handler(invalidEvent);
  expect(statusCode).toBe(400);
});

在这种情况下,应尽可能减少默认值(null0,空对象和数组,…),避免任何依赖于它们的特殊行为。

 类似资料:
  • 问题内容: 设置:我有一个用TypeScript编写的Node项目(纯Node,没有浏览器位)。我可以使用模块中的TypeScript编译器()来编译代码。到目前为止,一切都很好。 但是,我想使用Mocha编写测试,这就是我遇到的麻烦。我尝试了,但是不断出现以下错误: 看起来命令行最终被传递给,这显然不好。 问题答案: 对于任何尝试过 typescript-require 并遇到问题的人,您都可以

  • 问题内容: 我正在使用JavaScript测试运行程序“摩卡”。 我的测试失败了,因此我将使用进行调试。 但是运行测试时,没有输出(仅来自Mocha的测试结果)。看来Mocha已捕获并抑制了我的输出! 如何让Mocha显示输出?(对于失败的测试)? 编辑: 抱歉!- 在测试期间可以正常工作!我肯定一直期望它抑制输出,而且我没有正确检查自己的代码。感谢您的回应。所以…话虽如此…也许抑制通过测试的输出

  • 本教程上接教程第4部分。 我们已经建立一个网页投票应用,现在我们将为它创建一些自动化测试。 自动化测试简介 什么是自动化测试? 测试是检查你的代码是否正常运行的简单程序。 测试可以划分为不同的级别。 一些测试可能专注于小细节(某一个模型的方法是否会返回预期的值?), 其他的测试可能会检查软件的整体运行是否正常(用户在对网站进行了一系列的操作后,是否返回了正确的结果?)。这些其实和你早前在教程 1中

  • 问题内容: 我们有一个使用JQuery UI Sortable 的可排序列表,我们正在尝试使用Selenium自动进行排序。 看起来dragAndDrop函数应该可以工作,但是当我们调用它时,UI不会改变。但是,如果我们用Firebug来查看DOM,则会看到列表元素DID的顺序发生了变化。似乎只是UI无法刷新。 任何想法如何使其工作? 问题答案: 我们找不到可行的解决方案,因此我们只创建了辅助ja

  • 我正在一个命令行NodeJS项目中使用TypeScript,处理代码问题。第2天,我从以下几点开始: 和摩卡咖啡单元测试: 当我运行主程序时,调试器会很好地命中TS源中的断点,但是当我尝试调试(失败的)单元测试时,断点不会被命中。我猜单元测试运行程序只是直接执行生成的. js文件,没有正确处理源映射。 有没有办法强迫VisualStudio让我正确调试一个全TS项目?

  • 我试图弄清楚如何将Karma testrunner与Webpack和Typescript源文件一起使用。以该源文件作为唯一的测试文件为例: 测验规格ts 以及以下业力配置: 因果报应。配置。js 运行时未找到任何测试。浏览器将启动,但它表示找到0个测试。当我更改扩展名为并更新karma配置文件,因为它确实起作用,所以很明显是Typescript弄乱了它。 然而,当使用上面的配置手动运行webpac

  • 我正在尝试测试我的上传我是usig Junit,Mockmvc和Spring 你能帮帮我吗? 错误堆栈跟踪: [org.springframework.test.context.support.dependencyinjectiontestexecutionlistener@361cb7a1]准备测试实例[endpoint.security.tests.uploadtest@6F7918F0]or

  • 如何使用GoogleChrome的postman插件使用POST将FormData()对象发送到webapi。FormData()对象具有附加到其上的表单字段个人ID和MessageBody。我尝试过这样的东西,但没有用: