Chai 是一个流行的 JavaScript 测试库,它提供了一系列能够在浏览器和 Node.js 等环境下运行的断言库,可以方便地编写测试用例。其中,should 风格的 API 使得测试代码的可读性大大提高,但也有一些容易出现问题的地方,这篇文章将介绍一些我在使用 should 语法时遇到的问题和解决方式。
should 和 expect 的区别
在使用 should 之前,我们先来看一下 should 和 expect 的区别。下面是一个简单的示例:
-- -------------------- ---- ------- ----- ------ - ----------------------- ----- ------ - ----------------------- ----- ------ - ----------------------- -------------- ------- ---------- - ---------- ------- ------ ----- -------- ---------- - -------------- - -- --- --- ---------- ------- ------ ----- -------- ---------- - -------- - --------------- --- ---------- ------- ------ ----- -------- ---------- - -- - ------------------- --- ---
可以看到,这里使用了三种不同的语法来比较两个值是否相等。其中,assert 和 expect 都是比较常见的断言库,should 则是一个类似于 expect 的 API,但使用起来更加简单。上述代码的第一个测试用例使用了 assert,它需要先引入断言库,然后使用 assert 方法比较两个值是否相等。第二个测试用例则使用了 expect,它是一个独立的断言库,不需要先引入其它库,使用起来也比较简单。第三个测试用例则使用了 should,同样也不需要额外引入其它库,但它的语法略微有些不同。
should 的语法问题
和 expect 一样,should 提供了一系列的 API,可以帮助我们判断某个值是否符合预期。但因为 should 使用了一个全局的 Object.prototype.should 属性,也就是说,任意属性调用之后产生的值都具有 should 属性,这就导致了在某些情况下,should 的语法会出现问题。
问题一:should 语法会影响测试结果
第一个问题就是,should 语法会影响测试结果。下面是一个示例:
describe('test suite', function() { it('should compare two arrays', function() { [1, 2, 3].should.equal([1, 2, 3]); // 该语句会抛出 AssertionError }); });
在此示例中,我们测试的是两个数组是否相等。但是,使用 should 的语法会影响测试结果,该测试用例会抛出 AssertionError 错误。实际上,should 的原理是将之前的值转换为一个 should 对象,而这个操作可能改变了这个值本来的类型,导致了错误的测试结果。
我们可以使用 expect 对比两个数组,验证该语句的真实结果:
describe('test suite', function() { it('should compare two arrays', function() { expect([1, 2, 3]).to.eql([1, 2, 3]); // 该语句会通过测试 }); });
应该使用 eql 方法来比较两个数组,因为它会递归比较两个对象的所有属性。
问题二:should 的链式调用语法难以阅读
第二个问题是,should 的链式调用语法难以阅读。下面是一个示例:
-- -------------------- ---- ------- -------------- ------- ---------- - ---------- -------- ------ -------- ---------- - ----- ------ - - ----- ------- ---- --- ------- ------ -- -------------------------------------------------------- ------------------------------------------------------- ------------------------------------------------------------ ----------- --- ---
这个测试用例验证了一个 person 对象是否满足某些条件。可以看到,使用 should 的链式调用语法,可以一步步检查每个属性是否符合要求。但是,如果属性过多,甚至嵌套层次过深,那么这样的语法就会显得非常难以阅读。
我们可以使用 expect 对象实现类似的测试,不用链式调用语法,阅读上也更加良好:
-- -------------------- ---- ------- -------------- ------- ---------- - ---------- -------- ------ -------- ---------- - ----- ------ - - ----- ------- ---- --- ------- ------ -- -------------------------------------- ------------------------------------- ------------------------------------------ ----------- --- ---
问题三:should 语法不支持异步操作
第三个问题是,should 语法不支持异步操作。下面是一个示例:
-- -------------------- ---- ------- --------------- ------ ---------- - ---------- ------ ----- ----------- ---------- - -------------------------------------- -------- -- ------ --- --- -------- --------------- - ------ --- ----------------- ------- -- - ------------- -- - ----------------- -------- -- ----- --- -
在该测试用例中,我们测试了一个异步函数的返回值是否符合预期。但是,使用 should 会导致测试失败,因为它不支持异步操作。
我们可以使用 expect 对象来进行异步调用的测试,例如:
describe('async test', function() { it('should handle async operation', async function() { const result = await asyncFunction(); expect(result).to.equal('expected value'); }); });
我们需要在 it 函数中添加 async 关键字,然后使用 await 异步等待函数的返回值。
总结
本文介绍了使用 Chai 进行 BDD 风格测试时遇到的 should 语法问题及解决方式。总体来说,should 是一个很好用的测试库,但需要注意其语法特点,以免出现意外错误。在使用 should 时,我们应该避免影响测试结果的语法,尽量避免过度的链式调用,同时注意异步操作的处理。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/64f85621f6b2d6eab30700bc