Chai 中文文档 下载 App

.exist / .null / .undefined / .ok 存在性与真假值检查

存在性 vs 真假值

这两类断言容易混淆,先明确:

JS 中 falsy 值有六个:false、0、''、null、undefined、NaN。除这六个外其他都是 truthy。

.exist / .not.exist

expect(42).to.exist;          // 通过
expect(0).to.exist;           // 通过(0 不是 null/undefined)
expect('').to.exist;           // 通过(空字符串存在)
expect(null).to.not.exist;    // 通过
expect(undefined).to.not.exist;  // 通过

.exist 等价于 value !== null && value !== undefined,不涉及真假值判断。

典型场景:验证 API 返回了某个字段(不关心值是什么):

expect(response.body.user).to.exist;  // 字段存在即可

.ok / .not.ok

.ok 检查 truthy;.not.ok 检查 falsy:

expect('hello').to.be.ok;     // 通过(非空字符串是 truthy)
expect(1).to.be.ok;           // 通过
expect(true).to.be.ok;        // 通过
expect([1]).to.be.ok;         // 通过

expect(false).to.not.be.ok;   // 通过
expect(0).to.not.be.ok;       // 通过
expect('').to.not.be.ok;       // 通过
expect(null).to.not.be.ok;    // 通过
expect(undefined).to.not.be.ok;  // 通过
expect(NaN).to.not.be.ok;     // 通过

.ok 的另一个名字是 .true?不是——看下面的区别。

.true / .false

这两个是严格等于布尔值 true / false:

expect(true).to.be.true;      // 通过
expect(1).to.be.true;         // 失败——1 不是 true
expect(false).to.be.false;    // 通过
expect(0).to.be.false;        // 失败

对比:

expect(1).to.be.ok;           // 通过(truthy)
expect(1).to.be.true;         // 失败(=== true?不是)

三个概念的区别:

.null / .undefined

严格检查 === null / === undefined:

expect(null).to.be.null;       // 通过
expect(undefined).to.be.undefined;  // 通过

// 注意:在 JS 中 null == undefined 是 true,但 Chai 区分它们
expect(null).to.not.be.undefined;
expect(undefined).to.not.be.null;

为什么需要 .not.exist 而不是 .not.be.null.or.undefined?因为 .not.exist 同时排除两者,写法简洁:

// 推荐
expect(err).to.not.exist;

// 也可以但啰嗦
expect(err).to.be.null;   // 如果确实期望 null
expect(err).to.be.undefined;  // 如果确实期望 undefined

组合存在性 + 类型检查

检查值存在后再检查类型:

const user = await getUser();

expect(user).to.exist;
expect(user).to.be.an('object');
expect(user).to.have.property('name');

或者连写:

expect(user).to.exist.and.be.an('object').that.has.property('name');

assert 风格对应方法

assert.exists(value);
assert.notExists(value);
assert.isOk(value, [message]);         // truthy
assert.isNotOk(value, [message]);
assert.isNull(value);
assert.isNotNull(value);
assert.isUndefined(value);
assert.isDefined(value);
assert.isTrue(value);
assert.isFalse(value);

注意 assert 风格里的方法名:

常见误用

用 .ok 代替 .exist

// ❌ 错误:如果值是 0 或空字符串,会误判为不存在
expect(count).to.be.ok;  // count = 0 时失败,但 0 是合法值

// ✅ 如果只是想确认值存在
expect(count).to.exist;

用 .true 代替 .ok

// ❌ value 是 truthy 但不等于 true
expect(config.enabled).to.be.true;  // enabled = 1 时失败

// ✅ 如果接受 truthy
expect(config.enabled).to.be.ok;

// ✅ 如果严格要求布尔值
expect(config.enabled).to.be.true;   // 此时 enabled 必须是 true 不是 1

在异步场景忘记等待

// ❌ Promise 还没 resolve 就检查
expect(getUser()).to.exist;  // 检查的是 Promise 对象本身,永远 truthy

// ✅ 正确做法
const user = await getUser();
expect(user).to.exist;

下一步