我是javascript单元测试的新手,但我相信至少对一般的单元测试有所了解。

我正在尝试学习“ javascript方式”,并开始为我的客户端代码编写单元测试。

为此,我安装了以下库:
mocha.js和chai.js

出乎意料的是,一切进展顺利。
我设法轻松地包括了这些内容,并开始编写我的单元测试。

我正在使用ASP Core btw。尽管我发现VS2016是我使用过的该IDE的漏洞最多的版本(但我仅是一名专业专家,已经有5年了,所以我可能是错的),但新的MVC 6更改却为您提供了一种管理静态资源的简便方法(或客户端依赖项),让您使用Bower软件包管理器。

所以,回到测试。我从一小部分通用通用的简单javascript函数开始。尽管写得有些差,但他们提供了很好的练习。

但是,一段时间后,我需要开始嘲笑。通过用C#编写单元测试,我开始意识到这种类型的库的有用性。
由于这些概念绝非特定于C#而是仅适用于单元测试,因此我希望找到一个可提供这种功能的库-sinon.js。

再说一遍,一切进展顺利。

直到我不得不嘲笑诺言。

再次证明,有一个库可以帮助我解决这个问题-sinon-as-promised.js

经过相当多的努力,包括通过npm安装它,使用browserify之类的工具将其解析为一个脚本,以便在浏览器中使用等等,我相信我设法使它运行了。

此时,我可以执行以下操作:

let returnsPromise = sinon.stub($, "ajax").resolves('success');


这将使我成为一个“可实现的”对象(具有then()方法并且应该表现为承诺的东西)。
这里有一个小问题,它没有.done()和.fail()方法,在我的编码中我不知道它们是首选方法,但是我猜测有一种简单的方法可以将它们扩展到对象中。

在那之后,当我读到chai.js提供了一种管理承诺承诺的有效方法时,我甚至开始印象深刻。

我们在这里,我的问题。

我所说的关于柴的事情是“最终”的支持。一个让我做魔术的词,它避免了在then()的成功和错误回调中都使用.done()的情况,只是为了确保我们不会对诺言产生错误的肯定。

因此,应该这样使用它:

it('testing eventually', function () {
    let returnsPromise = sinon.stub($, "ajax").resolves('success');
    return expect(returnsPromise()).should.eventually.equal('success');
});


如果成功完成了想要的结果,这应该失败。

现在,您可以想象当我无法如愿以偿地跑步时我的失望。

我找不到该库的“浏览器友好”版本,因此,再次使用npm安装它之后,将其浏览器化为“应该在浏览器脚本中工作”,然后添加了它去派对。

但是,无论我做什么,在上面的示例中,都会出现以下错误:

TypeError: Cannot read property 'equal' of undefined
at Context.<anonymous> (js/miscellaneous-tests.js:94:58)


我将其解释为“我们最终不知道”是什么意思。这使我相信我添加chai-as-promised.js的方式无效。

此后,我尝试了很多事情。有些愚蠢,有些愚蠢,但是无论我如何尝试,都无法让代码“最终”理解

这些事情包括:


读取脚本并获取chai-as-promise的依赖关系并将其添加到解决方案中(既是browserify-ed,又以它们来自npm的形式),在第二种情况下,再次对其依赖项进行了相同的操作-直到我相信包裹丢失。
我尝试以多种不同的方式添加,删除文件,实际上我在编写此文件时会画一个空白-但我能想到的每种可能的组合-我都尝试过。
我用谷歌搜索“最终是不确定的”,类似的东西很多次,我认为谷歌对我有点生气,但我找不到我想要的东西
在某个时候,我开始在地板上画一个五角星形的大圆圈,但花了我一段时间(如今在办公室里找不到像处女的血液和蜡烛这样的东西)第二天回到办公室,那位清洁女工已将其擦除。


由于我没有主意,我希望你们中的一些人尝试在浏览器中进行一些javascript单元测试。

因为它涉及很多资源,说明和内容,并且此帖子已经超出了应有的时间,所以我创建了一个github存储库,在其中我已经上传了到目前为止所做的一切。

这是它的链接:
js-unit-test-mocking

顺便说一句,如果您不喜欢ASP或与Microsoft相关的任何内容,则运行它所需的所有内容都应该位于wwwroot中。

谢谢您的陪伴。抱歉,很长的帖子。

最佳答案

您的代码有两个问题:


您同时使用expectshould接口(expect(...).should.eventually.equal...)。您应同时使用一个或另一个,但不能同时使用两者。
您忘记使用chai.use的导出值调用chai-as-promised了。我从以下事实推断出这一点:如果我故意忽略了这一点,那么我会得到与您完全相同的错误,并且我不知道有任何其他方法可以获取该错误。


无论您想做什么,都必须转换chai-as-promised使其在浏览器中工作。由于您提到使用过browserify,因此我将在答案中使用它。您可以使用webpack甚至编写自己的脚本进行转换。

遵循两种一般策略。

仅变换chai-as-promised

这里的策略是将所有内容分开,仅转换chai-as-promised使其在浏览器中工作。这是一个说明性的测试文件:

const expect = chai.expect;
mocha.setup("bdd");

chai.should();

// Commenting out this line reproduces the exact error message
// reported in the question.
chai.use(chaiAsPromised);

// Incorrect use of should with expect.
it('testing eventually incorrectly', function () {
    return expect(Promise.resolve("success")).should.eventually.equal('success');
});

// Correct use of expect alone.
it('testing eventually with expect', function () {
    return expect(Promise.resolve("success")).eventually.equal('success');
});

// Correct use of should alone.
it('testing eventually with should', function () {
    return Promise.resolve("success").should.eventually.equal('success');
});


chai-as-promised用以下命令转换:

browserify -o chai-as-promised-built.js -s chaiAsPromised node_modules/chai-as-promised/lib/chai-as-promised.js


这实际上需要chai-as-promised.js并将其包装到代码中,以便它在CommonJS方言中正常导出的内容成为浏览器中的全局导出,并且该全局导出名为chaiAsPromised(这是-s选项的作用)。输出在chai-as-promise-built.js中,这是您需要在浏览器中加载的内容。

然后,您可以使用以下index.html文件:

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/xhtml; charset=utf-8"/>
    <link href="./node_modules/mocha/mocha.css" type="text/css" media="screen" rel="stylesheet" />
    <script type="text/javascript" src="./node_modules/mocha/mocha.js"></script>
    <script type="text/javascript" src="./node_modules/chai/chai.js"></script>
    <script type="text/javascript" src="./chai-as-promised-built.js"></script>
    <script type="text/javascript" src="./test.js"></script>
  </head>
  <body>
    <div id="mocha"></div>
    <script>
      mocha.run();
    </script>
  </body>
</html>


将所有内容捆绑到一个文件中

这里的策略是使用browserify将所有内容编译到一个文件中。对于某些项目,这是一个可行的选择。对于希望使用require编写代码而不是依赖于全局变量的项目,它也可能更可取。这是一个说明性的测试文件:

const chai = require("chai");
const chaiAsPromised = require("chai-as-promised");
const expect = chai.expect;
const mocha = require("mocha");
mocha.mocha.setup("bdd");

chai.should();

// Commenting out this line reproduces the exact error message
// reported in the question.
chai.use(chaiAsPromised);

// Incorrect use of should with expect.
it('testing eventually incorrectly', function () {
    return expect(Promise.resolve("success")).should.eventually.equal('success');
});

// Correct use of expect alone.
it('testing eventually with expect', function () {
    return expect(Promise.resolve("success")).eventually.equal('success');
});

// Correct use of should alone.
it('testing eventually with should', function () {
    return Promise.resolve("success").should.eventually.equal('success');
});


安装所需的模块后,请使用以下命令进行构建:

browserify -o built.js test.js


然后,您可以使用以下index.html文件加载它:

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/xhtml; charset=utf-8"/>
    <link href="./node_modules/mocha/mocha.css" type="text/css" media="screen" rel="stylesheet" />
    <script type="text/javascript" src="./built.js"></script>
  </head>
  <body>
    <div id="mocha"></div>
    <script>
      mocha.run();
    </script>
  </body>


您会看到第一个测试将失败,因为它尝试同时使用expectshould。随后的两个测试将通过。

如果您注释掉chai.use(chaiAsPromised);所在的行,则会得到与问题报告完全相同的错误消息。如果确实更改了代码,请记住使用browserify进行重建。

关于javascript - 配置JavaScript单元测试并 promise 声明,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40655599/

10-14 17:07