Skip to content

Add support for passing a function to stub.throws(...) #1511

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

Merged
merged 1 commit into from
Aug 6, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/release-source/release/stubs.md
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,11 @@ Causes the stub to throw an exception of the provided type.
Causes the stub to throw the provided exception object.


#### `stub.throws(function() { return new Error(); });`

Causes the stub to throw the exception returned by the function.


#### `stub.rejects();`

Causes the stub to return a Promise which rejects with an exception (`Error`).
Expand Down
4 changes: 4 additions & 0 deletions lib/sinon/behavior.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,10 @@ var proto = {

if (this.exception) {
throw this.exception;
} else if (this.exceptionCreator) {
this.exception = this.exceptionCreator();
this.exceptionCreator = undefined;
throw this.exception;
} else if (typeof this.returnArgAt === "number") {
return args[this.returnArgAt];
} else if (this.returnThis) {
Expand Down
18 changes: 14 additions & 4 deletions lib/sinon/default-behaviors.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,18 @@ var useLeftMostCallback = -1;
var useRightMostCallback = -2;

function throwsException(fake, error, message) {
if (typeof error === "string") {
fake.exception = new Error(message || "");
fake.exception.name = error;
if (typeof error === "function") {
fake.exceptionCreator = error;
} else if (typeof error === "string") {
fake.exceptionCreator = function () {
var newException = new Error(message || "");
newException.name = error;
return newException;
};
} else if (!error) {
fake.exception = new Error("Error");
fake.exceptionCreator = function () {
return new Error("Error");
};
} else {
fake.exception = error;
}
Expand Down Expand Up @@ -129,6 +136,7 @@ module.exports = {
fake.reject = false;
fake.returnValueDefined = true;
fake.exception = undefined;
fake.exceptionCreator = undefined;
fake.fakeFn = undefined;
},

Expand Down Expand Up @@ -158,6 +166,7 @@ module.exports = {
fake.reject = false;
fake.returnValueDefined = true;
fake.exception = undefined;
fake.exceptionCreator = undefined;
fake.fakeFn = undefined;
},

Expand All @@ -176,6 +185,7 @@ module.exports = {
fake.reject = true;
fake.returnValueDefined = true;
fake.exception = undefined;
fake.exceptionCreator = undefined;
fake.fakeFn = undefined;

return fake;
Expand Down
85 changes: 85 additions & 0 deletions test/stub-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,80 @@ describe("stub", function () {
assert.exception(stub, "Error");
});

it("throws an exception created using a function", function () {
var stub = createStub.create();

stub.throws(function () {
return new Error("not implemented");
});

assert.exception(stub, {
message: "not implemented"
});
assert.same(stub.firstCall.exception.message, "not implemented");
assert.contains(stub.firstCall.toString(), "not implemented");
});

describe("lazy instantiation of exceptions", function () {
var errorSpy;
beforeEach(function () {
this.originalError = global.Error;
errorSpy = createSpy(global, "Error");
// errorSpy starts with a call already made, not sure why
errorSpy.reset();
});

afterEach(function () {
errorSpy.restore();
global.Error = this.originalError;
});

it("uses a lazily created exception for the generic error", function () {
var stub = createStub.create();
stub.throws();

assert.isFalse(errorSpy.called);
assert.exception(stub, "Error");
assert.isTrue(errorSpy.called);
});

it("uses a lazily created exception for the named error", function () {
var stub = createStub.create();
stub.throws("TypeError", "typeerror message");

assert.isFalse(errorSpy.called);
assert.exception(stub, {
name: "TypeError",
message: "typeerror message"
});
assert.isTrue(errorSpy.called);
});

it("uses a lazily created exception provided by a function", function () {
var stub = createStub.create();

stub.throws(function () {
return new Error("not implemented");
});

assert.isFalse(errorSpy.called);
assert.exception(stub, {
message: "not implemented"
});
assert.isTrue(errorSpy.called);
});

it("does not use a lazily created exception if the error object is provided", function () {
var stub = createStub.create();
var exception = new Error();
stub.throws(exception);

assert.same(errorSpy.callCount, 1);
assert.exception(stub, exception);
assert.same(errorSpy.callCount, 1);
});
});

it("resets 'invoking' flag", function () {
var stub = createStub.create();
stub.throws();
Expand Down Expand Up @@ -872,6 +946,17 @@ describe("stub", function () {
assert(stub.threw("TypeError"));
});

it("handles threw properly for lazily instantiated Errors", function () {
var stub = createStub(this.object, "method");
stub.throws(function () {
return new TypeError();
});

assert.exception(this.object.method);

assert(stub.threw("TypeError"));
});

it("returns standalone stub without arguments", function () {
var stub = createStub();

Expand Down