.exist / .null / .undefined / .ok 存在性与真假值检查
存在性 vs 真假值
这两类断言容易混淆,先明确:
- 存在性:值是否为 null 或 undefined(JS 中只有这两个表示不存在)
- 真假值:在 JS 的 truthy / falsy 规则下是否为真
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?不是)
三个概念的区别:
.exist:非 null 非 undefined(存在性).ok:truthy(真假值).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 风格里的方法名:
assert.isOk(不是truthy)assert.exists/assert.notExists(没有.not前缀)assert.isTrue/assert.isFalse
常见误用
用 .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;