Skip to main content
On this page

Standard Assertions (@std/assert)

Overview Jump to heading

A library of assertion functions. If the assertion is false an AssertionError will be thrown which will result in pretty-printed diff of the failing assertion.

This module is browser compatible, but do not rely on good formatting of values for AssertionError messages in browsers.

import { assert } from "@std/assert";

assert("I am truthy"); // Doesn't throw
assert(false); // Throws `AssertionError`

Add to your project Jump to heading

deno add jsr:@std/assert

See all symbols in @std/assert on

什么是断言? Jump to heading

断言是一种必须为真的检查。如果不为真,程序将抛出一个带有有用信息和差异的 AssertionError,帮助你快速发现出错原因。

在测试中,断言用于验证行为。在应用代码中,它们可以用来记录和保护不变量(前置条件/后置条件)。在 TypeScript 中,一些断言(如 assert(condition))还能在检查后缩小类型范围。

何时使用 @std/assert? Jump to heading

该包中的工具使测试失败变得清晰且可操作(支持漂亮的差异显示和聚焦的消息)。通过内联编码期望,提高测试代码的可读性。

断言帮助快速失败,防止假设被违反而产生的隐性 bug。

在测试中应广泛使用断言来验证行为,捕获回归。

示例 Jump to heading

import {
  assert,
  assertAlmostEquals,
  assertArrayIncludes,
  assertEquals,
  assertExists,
  assertFalse,
  assertMatch,
  assertNotEquals,
  assertObjectMatch,
  assertRejects,
  assertStrictEquals,
  assertThrows,
} from "@std/assert";

// 基本的真值断言和类型缩小
const value: unknown = "hello";
assert(typeof value === "string", "Expected a string");
// value 现在被缩小为 string 类型

// 深度结构相等(对象/数组)
assertEquals({ a: 1, b: [1, 2] }, { a: 1, b: [1, 2] });
assertNotEquals([1, 2], [1, 2, 3]);

// 严格(引用/标识)相等,适用于基本类型和引用类型
assertStrictEquals(1, 1);
assertFalse(false);
assertExists("non-empty"); // 不是 null 或 undefined

// 模式匹配 & 数值比较
assertMatch("deno.land", /deno/);
assertAlmostEquals(0.1 + 0.2, 0.3, 1e-15);

// 集合
assertArrayIncludes([1, 2, 3], [2, 3]);
assertObjectMatch(
  { id: 42, name: "A", meta: { ok: true } },
  { name: "A", meta: { ok: true } }, // 子集必须匹配
);

// 错误断言:同步 vs 异步
assertThrows(() => JSON.parse("not json"), SyntaxError);
await assertRejects(() => fetch("https://deno.land/404"));

如何选择合适的相等检查 Jump to heading

断言相等主要有两种类型:

assertEquals Jump to heading

递归地按结构和内容比较值。对于数组,顺序必须一致;对于普通对象,键的顺序无关紧要。最适合比较序列化样式的数据(对象、数组、数字、字符串、布尔值)。

assertStrictEquals Jump to heading

检查两个操作数是否严格相同(基本类型)或引用相同(对象),语义类似于 Object.is

例如:
assertStrictEquals({ x: 1 }, { x: 1 }) 会失败(引用不同)
assertEquals({ x: 1 }, { x: 1 }) 通过
assertStrictEquals(NaN, NaN) 通过(类似 Object.is

示例 Jump to heading

// 深度相等 vs 严格相等
assertEquals({ a: 1 }, { a: 1 }); // ✅ 结构/内容相同
// assertStrictEquals({ a: 1 }, { a: 1 });   // ❌ 引用不同

const obj = { a: 1 };
assertStrictEquals(obj, obj); // ✅ 引用相同

// 数组:顺序在相等中很重要
assertEquals([1, 2, 3], [1, 2, 3]); // ✅
// assertEquals([1, 2, 3], [3, 2, 1]);       // ❌ 顺序不同

// 数字:浮点数比较
// 非精确数学运算建议使用 assertAlmostEquals
// assertEquals(0.1 + 0.2, 0.3);             // ❌
assertAlmostEquals(0.1 + 0.2, 0.3, 1e-15); // ✅
  • 使用 assertEquals 来比较数据的形状和值;当需要关心引用身份或基本类型的严格相等时,用 assertStrictEquals
  • 对部分对象检查,优先使用 assertObjectMatch 而非断言整个对象。
  • 比较大且嵌套复杂的结构时,assertEquals 详尽但效率较低——性能关键的热测试中,建议使用严格或有针对性的检查。

编写良好的失败提示信息 Jump to heading

所有断言函数的最后一个参数都可以传入可选的消息。编写这些消息帮助开发者理解失败发生的位置及修正方式。保持消息简洁且以用户为中心:

assert(Array.isArray(items), "items 必须是数组");
assertEquals(result.status, 200, "API 应返回 200 OK");

测试使用示例 Jump to heading

配合 Deno.test 使用:

Deno.test("adds numbers", () => {
  assertEquals(1 + 2, 3);
});

Deno.test("throws on invalid JSON", () => {
  assertThrows(() => JSON.parse("nope"), SyntaxError);
});

Deno.test("rejects for failed fetch", async () => {
  await assertRejects(() => fetch("https://deno.land/404"));
});

小贴士 Jump to heading

  • 处理浮点数运算时,使用带容差的 assertAlmostEquals
  • 对于部分对象的检查,使用 assertObjectMatch 而非整形断言。
  • assert(condition) 在 TS 中带有断言签名 (asserts condition),可以缩小类型范围。
  • 针对 Promise 推荐用 assertRejects,针对同步代码用 assertThrows,不要混用。

参见 Jump to heading

  • @std/expect 提供 Jest 风格的 BDD 断言 API,如果你喜欢链式匹配器,可以考虑使用。

你找到了你需要的东西吗?

编辑此页面
隐私政策