I'm trying to unit test an expected javascript exception in a dependent service with QUnit.
The following block is the code under test. It's TypeScript using WinJS promises. The constructor accepts a _dataLayer and _errorService as dependencies. If the _dataLayer throws a specific exception, the code under test attempts to recover from the error.
module Services {
export class MyService {
constructor(private _dataLayer, private _errorService) {
}
private _items: any[];
getItems() {
var promise = this._dataLayer.getItems()
.then((items) => {
this._items = items;
return this._items;
})
.then(null, (error) => {
if (error.status === 404) {
// tolerate this error and recover
this._items = [];
return this._items;
}
// Display an error message
this._errorService.handleError(error);
});
return promise;
}
}
}
The following unit test attempts to prove the code under test can recover from the expected exception.
QUnit.test("getItems handles _dataLayer.getItems HTTP 404", function (assert) {
// arrange
var done = assert.async();
var _dataLayer = {
getItems: function () {
throw { status: 404 };
}
};
var svc = new Services.MyService(_dataLayer, null);
// act
svc.getItems().then(function (items) {
// assert
assert.strictEqual(items.length, 0);
done();
});
});
The code under test is correctly recovering from the error, I just can't prove that with QUnit. When the test is run, it appears QUnit fails the test simply because an exception is thrown, regardless of how it's handled.
I'm not testing that an error was thrown. The test is to prove the thrown error us successfully handled.
Is there a way to construct a QUnit test so the code under test will pass the HTTP 404 test?
Doh! I overlooked the bug in my QUnit test. It was returning an immediate (error) response, and it should have been returning a promise that wraps an error.
The hint was QUnit doesn't know about the internals of the promise, to the fact that an error was bubbling up from within a promise should have told me QUnit wasn't dealing with a promise at all!
The following revision to the QUnit test correctly proves the service is recovering from an HTTP 404 error:
QUnit.test("getItems handles _dataLayer.getItems HTTP 404", function (assert) {
// arrange
var done = assert.async();
var _dataLayer = {
getItems: function () {
return WinJS.Promise.wrapError({
status: 404
});
}
};
var svc = new Services.MyService(_dataLayer, null);
// act
svc.getItems().then(function (items) {
// assert
assert.strictEqual(items.length, 0);
done();
});
});