-
Notifications
You must be signed in to change notification settings - Fork 11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
test.promise fails where standard bluebird does not #5
Comments
Hello, it's strange, I will test today. |
var request = noder.$di.get('authRequest');
request.getAsync({})
.spread(function (res, body) {
res.statusCode.must.be(200);
body.must.be('ERROR:999:invalid command');
})
.catch(function (err) {
test.fail(err.message);
})
.finally(done); Here the errors are unhandled, Bluebird catches the error and ensures that there are no error which breaks the script execution, this behavior allow to handle the errors (even in the catch method). With Bluebird, to be able to rethrow an error, you should add .done() at the end: var request = noder.$di.get('authRequest');
request.getAsync({})
.spread(function (res, body) {
res.statusCode.must.be(200);
body.must.be('ERROR:999:invalid command');
})
.catch(function (err) {
test.fail(err.message);
})
.finally(done)
.done(); This works: var test = require('unit.js');
test.$di.factory('httpRequest', function() {
return test.promisifyAll(require('request'));
});
describe('HTTP promise', function() {
it('should passes', function(done) {
var request = test.$di.get('httpRequest');
request.getAsync('http://google.com')
.spread(function (res, body) {
test
.number(res.statusCode)
.is(200)
.string(body)
.contains('google')
;
})
.catch(function (err) {
test.fail(err.message);
})
.finally(done)
.done();
});
it('should not pass', function(done) {
var request = test.$di.get('httpRequest');
request.getAsync()
.spread(function (res, body) {
test
.number(res.statusCode)
.is(200)
.string(body)
.contains('google')
;
})
.catch(function (err) {
test.fail(err.message);
})
.finally(done)
.done()
});
}); But if I remove the .done() it('should not pass', function(done) {
var request = test.$di.get('httpRequest');
request.getAsync()
.spread(function (res, body) {
test
.number(res.statusCode)
.is(200)
.string(body)
.contains('google')
;
})
.catch(function (err) {
test.fail(err.message);
})
.finally(done);
}); This test case passes with a warning in the console: You can .catch(function (err) {
test.dump(err).fail(err.message);
}) In passing, var request = test.$di.get('authRequest'); All noder API is usable with the |
Yes, that was my mistake on the missing |
Indeed it's a subtlety of Bluebird, but it's handy especially in a context of unit tests where we need sometime rethrow and sometime just test the error. For nonce, I just added this clarification in the doc.
This passes 'use strict';
var test = require('unit.js');
test.$factory('httpRequest', function() {
return test.promisifyAll(require('request'));
});
describe('HTTP promise', function() {
it('must be a promise', function() {
var request = test.$di.get('httpRequest');
test.promise.is(request.getAsync('http://google.com')).must.be.true();
});
it('should work with `given()`', function(done) {
var request = test.$di.get('httpRequest');
test.promise
.given(request.getAsync('http://google.com'))
.spread(function (res, body) {
test
.number(res.statusCode)
.is(200)
.string(body)
.contains('google')
;
})
.catch(function (err) {
test.fail(err.message);
})
.finally(done)
.done();
});
}); Maybe your problem is your service |
It's a factory: 'use strict';
module.exports.__noder = function requestPlugin(noder) {
noder.$factory('authRequest', ['config'], function (config) {
var request = noder.request.defaults({
url: 'http://us-proxies.com/api.php?api&uid=' +
config.get('US_PROXIES_UID') +
'&pwd=' +
config.get('US_PROXIES_PWD')
});
return noder.Promise.promisifyAll(request);
});
return noder;
};
'use strict';
module.exports.__noder = function promisePlugin(noder) {
noder.$require('Promise', 'bluebird');
return noder;
}; My test spec: 'use strict';
var noder;
describe('Request', function () {
before(function () {
process.env.US_PROXIES_UID = '1234';
process.env.US_PROXIES_PWD = 'abc123';
require('../mock-api');
noder = require('../../');
});
describe('authRequest', function () {
it('should be a request that authenticates to US Proxies API', function (done) {
var request = noder.$di.get('authRequest');
test.promise
.given(request.getAsync({}))
.spread(function (res, body) {
res.statusCode.must.be(200);
body.must.be('ERROR:999:invalid command');
})
.catch(function (err) {
test.fail(err.message);
})
.finally(done)
.done();
// This works:
// request.getAsync({})
// .spread(function (res, body) {
// res.statusCode.must.be(200);
// body.must.be('ERROR:999:invalid command');
// })
// .catch(function (err) {
// test.fail(err.message);
// })
// .finally(done)
// .done();
});
after(function () {
delete process.env.US_PROXIES_UID;
delete process.env.US_PROXIES_PWD;
});
}); Perhaps yours works because the promisification is coming from the same bluebird that it being used in the test, whereas, in my case, the |
Good catch, I struggled all morning. Bluebird seems impervious to a single instance. Maybe there is a solution provided for that, I have not found. So you must use either directly Or the same instance of Bluebird. For that, you need to install Bluebird before Unit.js. NPM will not install Bluebird in dependency of Unit.js given that it will be already in node_modules. Personally, in a case like this, I use directly to
Or for the context (BDD style) related to the current test. it('Update user', function(done) {
test.promise
.given(request.getAsync('http://localhost:3000/api/user/42/update'))
// ...test case
});
it('Delete user', function(done) {
test.promise
.given(request.getAsync('http://localhost:3000/api/user/42/delete'))
// ...test case
}); |
I opened an issue Bluebird #398. |
Works with test.promise.resolve() https://github.com/Nicolab/bluebird-test-case/blob/master/test/index.js#L38 So I should be able to make a patch :) |
Fixed and released in the v1.1.1 |
👍 |
In complement, it's also possible to write it('should pass', function(done) {
var request = test.$di.get('httpRequest');
request.getAsync()
.spread(function (res, body) {
test
.number(res.statusCode)
.is(200)
.string(body)
.contains('google')
;
})
.catch(function (err) {
test.fail(err.message);
done(err);
})
.done();
}); With the |
This works:
This does not:
I
promisifyAll
'd request with bluebird (and set a default URL, which is why I'm only passing an empty object parameter). Iftest.promise
is truly just bluebird, then I don't see why the second case is failing.So I stepped through and the problem is that inside of
given
, it thinks the result is an object but not a Promise:But it's most definitely a Promise, straight out of bluebird (same version). In fact, this passes:
However, this does not:
The text was updated successfully, but these errors were encountered: