我正在尝试使用Flutures and Sanctuary将代码片段从好的旧版Promises转换成某种东西:
https://codesandbox.io/embed/q3z3p17rpj?codemirror=1
现在,通常,我使用Promises,可以使用sinonjs之类的库来兑现承诺,即伪造其结果,强制解决,拒绝等。
这是基础,因为它可以帮助测试多个分支方向并确保一切正常进行。
但是对于Flutures,情况有所不同。不能简单地将Fluture存入存根,而我也找不到任何可以帮助您的
答案 0 :(得分:1)
我不确定,但是那些Flutures(这个名字!...没关系,API看起来很酷)是普通对象,就像promises一样。他们只有更复杂的API和不同的行为。
此外,您可以使用Future.of
,Future.reject
轻松创建“模拟”素材,而不用进行真正的API调用。
是的,sinon包含resolves
,rejects
之类的糖辅助器,但它们只是可以用callsFake
实现的包装器。
因此,您可以轻松地创建存根来创建类似这样的内容。
someApi.someFun = sinon.stub().callsFake((arg) => {
assert.equals(arg, 'spam');
return Future.of('bar');
});
然后,您可以像其他任何API一样对其进行测试。 唯一的问题是“异步性”,但是可以像下面建议的那样解决。
// with async/await
it('spams with async', async () => {
const result = await someApi.someFun('spam).promise();
assert.equals(result, 'bar');
});
// or leveraging mocha's ability to wait for returned thenables
it('spams', async () => {
return someApi.someFun('spam)
.fork(
(result) => { assert.equals(result, 'bar');},
(error) => { /* ???? */ }
)
.promise();
});
答案 1 :(得分:0)
正如Zbigniew所建议的那样,Future.of
和Future.reject
是使用普通的旧javascript或您喜欢的任何工具或框架进行模拟的绝佳候选者。
要回答您的问题的第2部分,请给出如何使用Fluture进行TDD的任何具体建议。当然,没有应该做到的一种正确方法。但是,如果您打算在整个应用程序中全部使用Futures,我建议您花一点时间在可读性和编写测试的便利性上。
这不仅适用于期货,还适用于您经常包含在测试中的任何内容。 这个想法是,当您浏览测试用例时,您会看到开发人员的意图,而不是样板化地让您的测试执行您需要的测试。
在我的情况下,我使用BDD风格的mocha&chai(当时提供)。 为了便于阅读,我创建了这些辅助函数。
const {expect} = require('chai');
exports.expectRejection = (f, onReject) =>
f.fork(
onReject,
value => expect.fail(
`Expected Future to reject, but was ` +
`resolved with value: ${value}`
)
);
exports.expectResolve = (f, onResolve) =>
f.fork(
error => expect.fail(
`Expected Future to resolve, but was ` +
`rejected with value: ${error}`
),
onResolve
);
如您所见,没有什么神奇的事情发生,我只是使意外结果失败,让您处理预期的路径,从而对此进行更多声明。
现在一些测试看起来像这样:
const Future = require('fluture');
const {expect} = require('chai');
const {expectRejection, expectResolve} = require('../util/futures');
describe('Resolving function', () => {
it('should resolve with the given value', done => {
// Given
const value = 42;
// When
const f = Future.of(value);
// Then
expectResolve(f, out => {
expect(out).to.equal(value);
done();
});
});
});
describe('Rejecting function', () => {
it('should reject with the given value', done => {
// Given
const value = 666;
// When
const f = Future.of(value);
// Then
expectRejection(f, out => {
expect(out).to.equal(value);
done();
});
});
});
跑步应该给出一通一失。
✓ Resolving function should resolve with the given value: 1ms
1) Rejecting function should reject with the given value
1 passing (6ms)
1 failing
1) Rejecting function
should reject with the given value:
AssertionError: Expected Future to reject, but was resolved with value: 666
请记住,应将其视为异步代码。这就是为什么我总是接受done
函数作为it()
中的参数并在预期结果的末尾调用它的原因。或者,您可以更改帮助程序功能以返回承诺并让摩卡(mocha)处理该承诺。