- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我的设置使用chai
、sinon
、chai-sinon
、chai-as-promised
、babel
和 es6 语法。
我有以下(简化的)代码
// example.js
'use strict';
import EventEmitter from 'events';
class Dispatcher extends EventEmitter {
send(x) {
doSomethingAsync() // promise is NOT returned
.then(() => {
this.emit('sent');
})
.catch((err) => {
this.emit('error', err);
});
}
}
注意:不返回来自 doSomethingAsync 的 promise 。 (而且永远不会)
这是我的(简化的)测试文件
let dispatcher;
let onSent;
let onError;
beforeEach(() => {
dispatcher = new Dispatcher();
onSent = sinon.stub();
onError= sinon.stub();
dispatcher.on('sent', onSent);
dispatcher.on('error', onError);
});
describe('send', () => {
it('should emit "error" on sendFn error instead of "sent"', () => {
... set up state for failure ...
dispatcher.send(...);
... What do I do here or how do I wrap the following? ...
expect(onSent).not.to.have.been.called;
expect(onError).to.have.been.called;
});
});
如果我可以从 doSomethingAsync
返回 promise 作为 send
的结果,我知道该怎么做,但这里不是这种情况。我所知道的是最终会发出“已发送”或“错误”事件。
我理想的语法是这样的:
expect(onError).to.eventually.have
但是,那是行不通的。只需将 expect
包装在一个新的 promise 中,我就可以获得一个无错误的版本,如下所示。但我不知道为什么会这样。
// This one works for some unknown reason!
it('should emit "send" on send success', () => {
... set up state for success ...
dispatcher.send(...);
return Promise.resolve().then(() => {
expect(onSent).to.have.been.called;
expect(onError).not.to.have.been.called;
});
});
如果我能以公开内部 promise 的方式重构代码,那么这将很容易解决。我在其他情况下这样做过无数次。然而,我的问题是非常具体如何解决这个精确模式;即如何测试无法访问的 promise 或异步代码的副作用,特别是当我无法重构代码以公开 promise 时围绕事件发射器。
我至少尝试了以下方法,看看我是否可以在测试调用期望之前触发所需的发送函数以完成其所有内部回调/ promise
sinon.useFakeTimers
控制时间 提前致谢。
编辑:
好吧,这是完全荒谬的,但这里有一个解决方案,适用于已解决和已拒绝的 promise :
it('should behave as expected already!', (done) => {
... set up for failure or success as desired
dispatcher.send();
process.nextTick(() => {
Promise.resolve().then(() => {
... expectations ...
done();
});
});
});
我认为这是可行的,因为(我完全是在猜测!)我假设抛出的错误或拒绝的 promise 会在当前 tick 中立即处理,而已解决的 promise 会在下一个 tick 中排队。所以...... process.nextTick
确保我们将在下一个滴答中排队这个函数,允许所有捕获/错误完成,并且 Promise.resolve 确保它在任何已经排队的之后排队 promise 已兑现。顺便说一句,您也可以切换顺序或 nextTick 和 promise.resolve(),它工作得很好。
NB 如果事件是真正异步发出的(例如在它们自己的 process.nextTick
中),那么您必须有一个 3 级嵌套。Promise-nextTick-promise或 nextTick-promise-nextTick。
我的话太乱了!
...不过还是比超时好 :D
最佳答案
由于测试不会等待您正在测试的代码块来解决/拒绝 promise ,因此断言将不起作用。
你的分析都是正确的,但解决的方法是解决断言中的 promise 。
我对您的代码进行了一些更改并使其正常工作。
我已经让 doSomethingAsync
返回 promise (我认为这是正确的解决方案)
//待测代码
import EventEmitter from 'events';
const doSomethingAsync = async (x) => {
return x;
};
class Dispatcher extends EventEmitter {
send(x) {
return doSomethingAsync(x)
.then((res) => {
this.emit('sent');
})
.catch((err) => {
this.emit('error', err);
});
}
}
export default Dispatcher;
//测试
选项 1:使用 await
import sinon from 'sinon';
import { expect } from 'chai';
import Dispatcher from '../dispatcher';
describe('send', () => {
let dispatcher;
let onSent;
let onError;
beforeEach(() => {
dispatcher = new Dispatcher();
onSent = sinon.stub();
onError = sinon.stub();
dispatcher.on('sent', onSent);
dispatcher.on('error', onError);
});
it('Test 1: should emit "error" on sendFn error instead of "sent"', async () => {
await dispatcher.send('hello');
expect(onSent.callCount).to.equal(1);
expect(onError.callCount).to.equal(0);
});
});
//结果
yarn run spec
send ✓ should emit "error" on sendFn error instead of "sent"
1 passing (1s)
✨ Done in 4.18s.
选项 2:有 promise
在测试中,您可以看到我在 dispatcher.send
上使用 await,或者您也可以使用 promises 断言,如下所示
it('Test 2: should emit "error" on sendFn error instead of "sent"', () => {
let error = false;
dispatcher.send('hello').then(() => {
expect(onSent.callCount).to.equal(1);
expect(onError.callCount).to.equal(0);
}).catch(() => {
error = true;
})
expect(error).to.equal(false);
});
PS:- 如果您不想返回 promise,那么第一个测试用例(使用 await 的那个)将通过,第二个将失败。
关于node.js - Mocha Chai Sinon 测试无法访问的 promise/async/event-emitter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43472844/
我正在使用 mocha 和 chai 进行 TDD 以测试一些 NodeJS 脚本,每次我想再次运行测试时都必须运行“mocha”。 有没有办法设置 mocha 和 chai 在我保存源文件后立即运行
如果任何测试失败,我正在尝试配置 mocha 以重试整个套件。 我导航到一个 URL,然后填充一个表单并提交,然后用户被重定向,如果找到某个元素,则最后一次测试通过。 如果找不到该元素,我需要再次导航
我想知道是否有办法让 mocha 列出它将执行的所有测试。当我使用 mocha --help 列出它们时,我没有看到任何合理的选项;有几个报告者,但似乎没有一个旨在列出将要处理的文件(或命名将要运行的
before()、after()、beforeEach()、afterEach() 等 mocha Hook 无法正常工作。 only 方法也不起作用。 beforeEach 都没有被调用。我得到一个
我已经看到很多关于此的问题,但所有修复都不适用于我的代码。 我做错了什么?我的 beforeEach 没有被执行。 这是单元测试代码: var assert = require('assert');
如何在 mocha 测试之间共享资源(例如连接)? cookies.test.js: describe('Cookies', function() { it('setCookie()', func
我正在尝试以编程方式运行 mocha。 runner的代码如下: var Mocha = require("mocha"); var mocha = new Mocha(); mocha.report
我正在遵循此 tutorial 的第 1 步 我有以下文件夹结构: ├── lib │ ├── json │ │ ├── messages.json │ │ └── testMessages.json
我希望能够扩展 mocha 测试结果并从可用的 mocha 对象中收听它们。首先,我正在寻找“通过”结果。 看起来他们可能是从套件中订阅的,但我不确定如何...... 我尝试了以下我认为会听到我所有测
我正在运行此测试(简化),该测试按预期失败了……但是,尽管失败了,但它仍要等待20秒的全部超时时间。如何使它立即失败? it("should fail before timeout", functio
我是Java语言世界的新手,主要涉足OOP。我试图在网上查找Karma和 Mocha 之间的明显区别,但徒劳无功。我知道Karma是一个测试运行器,而Mocha是一个单元测试框架,但是Mocha也有自
我有一段代码,其中某些测试在 CI 环境中总是会失败。我想根据环境条件禁用它们。 如何在运行时执行期间以编程方式跳过 mocha 中的测试? 最佳答案 您可以通过在describe或it block
我想使用 chai 应该断言检查我的响应对象是否包含提到的属性。 下面是我的代码片段: chai.request(app) .post('/api/signup') .
例如,默认情况下,背景颜色为绿色或红色。我想将绿色/红色作为前景,将背景作为我的默认颜色(白色)。 因为在浅色终端配色方案上很难看到任何东西,因为前景是黑色的,而背景会变成红色或绿色。 最佳答案 在
有没有办法在 mocha 记者中获取当前测试的文件名? 我在基础和示例中找不到任何内容。 最佳答案 实际上,文件名在 中传递给了 Suite文件 Mocha 中的字段从 this 开始拉取请求。只是现
在我走向 TDD 的过程中,我使用了 Mocha、chai 和 sinon。 那里肯定有一个学习曲线。 我的目标是编写一个测试来验证 method4 是否已执行。我如何做到这一点? //MyData.
我正在使用mocha和chai作为断言。 我在规范中有几个主张: Exp1.should.be.true Exp2.should.be.true Exp3.should.be.true 如果其中之一失
根据 Mocha 文档,“Mocha 测试串行运行”这意味着按照它们的定义顺序。 我的问题是:是什么让 异步 (带有完成回调)测试不同于 同步 ? 最佳答案 您通过传递给 it 来告诉 Mocha 测
我正在尝试将 mocha 绑定(bind)写入 PureScript 并且对 Control.Monad.Eff 完全感到困惑 describe(function(){ //do stuff }
我对 mocha 框架有点陌生。此代码应该抛出异常,但不会。 (为简单起见,将所有代码放入测试中) describe("Test", function() { it("this should
我是一名优秀的程序员,十分优秀!