此页面

断言

为了帮助开发人员编写测试,Deno 标准库附带了一个内置的 断言模块,可以从 https://deno.land/std/assert/mod.ts 导入。

import { assert } from "https://deno.land/[email protected]/assert/mod.ts";

Deno.test("Hello Test", () => {
  assert("Hello");
});

⚠️ 一些流行的断言库,如 Chai,也可以在 Deno 中使用,例如使用示例请参见 https://deno.land/std/testing/chai_example.ts

断言模块提供了 14 个断言

  • assert(expr: unknown, msg = ""): asserts expr
  • assertEquals(actual: unknown, expected: unknown, msg?: string): void
  • assertExists(actual: unknown, msg?: string): void
  • assertNotEquals(actual: unknown, expected: unknown, msg?: string): void
  • assertStrictEquals(actual: unknown, expected: unknown, msg?: string): void
  • assertAlmostEquals(actual: number, expected: number, epsilon = 1e-7, msg?: string): void
  • assertInstanceOf(actual: unknown, expectedType: unknown, msg?: string): void
  • assertStringIncludes(actual: string, expected: string, msg?: string): void
  • assertArrayIncludes(actual: unknown[], expected: unknown[], msg?: string): void
  • assertMatch(actual: string, expected: RegExp, msg?: string): void
  • assertNotMatch(actual: string, expected: RegExp, msg?: string): void
  • assertObjectMatch( actual: Record<PropertyKey, unknown>, expected: Record<PropertyKey, unknown>): void
  • assertThrows(fn: () => void, ErrorClass?: Constructor, msgIncludes?: string | undefined, msg?: string | undefined): Error
  • assertRejects(fn: () => Promise<unknown>, ErrorClass?: Constructor, msgIncludes?: string | undefined, msg?: string | undefined): Promise<void>

除了上述断言之外,快照模块 还公开了 assertSnapshot 函数。此模块的文档可以在 此处 找到。

断言 跳转到标题

assert 方法是一个简单的“真值”断言,可用于断言任何可以推断为真的值。

Deno.test("Test Assert", () => {
  assert(1);
  assert("Hello");
  assert(true);
});

存在 跳转到标题

assertExists 可用于检查值是否不是 nullundefined

assertExists("Denosaurus");
Deno.test("Test Assert Exists", () => {
  assertExists("Denosaurus");
  assertExists(false);
  assertExists(0);
});

相等 跳转到标题

有三个相等断言可用,assertEquals()assertNotEquals()assertStrictEquals()

assertEquals()assertNotEquals() 方法提供了一般的相等性检查,能够断言基本类型和对象之间的相等性。

Deno.test("Test Assert Equals", () => {
  assertEquals(1, 1);
  assertEquals("Hello", "Hello");
  assertEquals(true, true);
  assertEquals(undefined, undefined);
  assertEquals(null, null);
  assertEquals(new Date(), new Date());
  assertEquals(new RegExp("abc"), new RegExp("abc"));

  class Foo {}
  const foo1 = new Foo();
  const foo2 = new Foo();

  assertEquals(foo1, foo2);
});

Deno.test("Test Assert Not Equals", () => {
  assertNotEquals(1, 2);
  assertNotEquals("Hello", "World");
  assertNotEquals(true, false);
  assertNotEquals(undefined, "");
  assertNotEquals(new Date(), Date.now());
  assertNotEquals(new RegExp("abc"), new RegExp("def"));
});

相比之下,assertStrictEquals() 提供了一个更简单、更严格的基于 === 运算符的相等性检查。因此,它不会断言两个相同对象的实例,因为它们在引用上不会相同。

Deno.test("Test Assert Strict Equals", () => {
  assertStrictEquals(1, 1);
  assertStrictEquals("Hello", "Hello");
  assertStrictEquals(true, true);
  assertStrictEquals(undefined, undefined);
});

assertStrictEquals() 断言最适合用于对两个基本类型进行精确检查。

数字的相等 跳转到标题

在测试数字之间的相等性时,务必牢记,其中一些数字无法通过 IEEE-754 双精度浮点表示法准确地描绘。

这在处理十进制数时尤其如此,在某些情况下 assertStrictEquals() 可能有效,但在其他情况下则无效

import {
  assertStrictEquals,
  assertThrows,
} from "https://deno.land/[email protected]/assert/mod.ts";

Deno.test("Test Assert Strict Equals with float numbers", () => {
  assertStrictEquals(0.25 + 0.25, 0.25);
  assertThrows(() => assertStrictEquals(0.1 + 0.2, 0.3));
  //0.1 + 0.2 will be stored as 0.30000000000000004 instead of 0.3
});

相反,assertAlmostEquals() 提供了一种方法来测试给定的数字是否足够接近,以被认为相等。默认容差设置为 1e-7,但可以通过传递第三个可选参数来更改它。

import {
  assertAlmostEquals,
  assertThrows,
} from "https://deno.land/[email protected]/assert/mod.ts";

Deno.test("Test Assert Almost Equals", () => {
  assertAlmostEquals(0.1 + 0.2, 0.3);
  assertAlmostEquals(0.1 + 0.2, 0.3, 1e-16);
  assertThrows(() => assertAlmostEquals(0.1 + 0.2, 0.3, 1e-17));
});

实例类型 跳转到标题

要检查对象是否为特定构造函数的实例,可以使用 assertInstanceOf()。这还有一个额外的好处,它可以让 TypeScript 知道传入的变量具有特定类型。

import { assertInstanceOf } from "https://deno.land/[email protected]/assert/mod.ts";

Deno.test("Test Assert Instance Type", () => {
  const variable = new Date() as unknown;

  assertInstanceOf(variable, Date);

  // This won't cause type errors now that
  // it's type has been asserted against.
  variable.getDay();
});

包含 跳转到标题

有两种方法可用于断言值包含一个值,assertStringIncludes()assertArrayIncludes()

assertStringIncludes() 断言对字符串进行简单的包含检查,以查看它是否包含预期的字符串。

Deno.test("Test Assert String Contains", () => {
  assertStringIncludes("Hello World", "Hello");
});

assertArrayIncludes() 断言稍微高级一些,它可以在数组中找到一个值,以及在数组中找到一组值。

Deno.test("Test Assert Array Contains", () => {
  assertArrayIncludes([1, 2, 3], [1]);
  assertArrayIncludes([1, 2, 3], [1, 2]);
  assertArrayIncludes(Array.from("Hello World"), Array.from("Hello"));
});

正则表达式 跳转到标题

您可以通过 assertMatch()assertNotMatch() 断言来断言正则表达式。

Deno.test("Test Assert Match", () => {
  assertMatch("abcdefghi", new RegExp("def"));

  const basicUrl = new RegExp("^https?://[a-z.]+.com$");
  assertMatch("https://www.google.com", basicUrl);
  assertMatch("http://facebook.com", basicUrl);
});

Deno.test("Test Assert Not Match", () => {
  assertNotMatch("abcdefghi", new RegExp("jkl"));

  const basicUrl = new RegExp("^https?://[a-z.]+.com$");
  assertNotMatch("https://deno.land/", basicUrl);
});

对象 跳转到标题

使用 assertObjectMatch 检查 JavaScript 对象是否与对象的属性子集匹配。

// Simple subset
assertObjectMatch(
  { foo: true, bar: false },
  {
    foo: true,
  },
);

抛出 跳转到标题

在 Deno 中,有两种方法可以断言某件事是否抛出错误,assertThrows()assertRejects()。这两个断言都允许您检查是否抛出了 错误,抛出的错误类型以及错误消息是什么。

这两个断言之间的区别在于 assertThrows() 接受一个标准函数,而 assertRejects() 接受一个返回 Promise 的函数。

assertThrows() 断言将检查是否抛出了错误,并且可以选择检查抛出的错误是否为正确的类型,并断言错误消息与预期一致。

Deno.test("Test Assert Throws", () => {
  assertThrows(
    () => {
      throw new Error("Panic!");
    },
    Error,
    "Panic!",
  );
});

assertRejects() 断言稍微复杂一些,主要是因为它处理 Promise。但基本上它会捕获 Promise 中抛出的错误或拒绝。您还可以选择检查错误类型和错误消息。这可以类似于 assertThrows() 一起使用,但使用异步函数。

Deno.test("Test Assert Throws Async", async () => {
  await assertRejects(
    () => {
      return new Promise(() => {
        throw new Error("Panic! Threw Error");
      });
    },
    Error,
    "Panic! Threw Error",
  );

  await assertRejects(
    () => {
      return Promise.reject(new Error("Panic! Reject Error"));
    },
    Error,
    "Panic! Reject Error",
  );
});

自定义消息 跳转到标题

Deno 的每个内置断言都允许您覆盖标准的 CLI 错误消息(如果您愿意)。例如,此示例将输出“值不匹配!”而不是标准的 CLI 错误消息。

Deno.test("Test Assert Equal Fail Custom Message", () => {
  assertEquals(1, 2, "Values Don't Match!");
});

自定义测试 跳转到标题

虽然 Deno 带有强大的 断言模块,但总有一些特定于项目的内容可以添加。创建 自定义断言函数 可以提高可读性并减少代码量。

import { AssertionError } from "https://deno.land/[email protected]/assert/mod.ts";

function assertPowerOf(actual: number, expected: number, msg?: string): void {
  let received = actual;
  while (received % expected === 0) received = received / expected;
  if (received !== 1) {
    if (!msg) {
      msg = `actual: "${actual}" expected to be a power of : "${expected}"`;
    }
    throw new AssertionError(msg);
  }
}

在您的代码中像这样使用此匹配器

Deno.test("Test Assert PowerOf", () => {
  assertPowerOf(8, 2);
  assertPowerOf(11, 4);
});