diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index 0d54f813..cd39aee7 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -9454,6 +9454,16 @@ getJasmineRequireObj().SpyRegistry = function(j$) { obj[methodName] = spiedMethod; + // Check if setting the property actually worked. Some objects, such as + // localStorage in Firefox and later Safari versions, have no-op setters. + if (obj[methodName] !== spiedMethod) { + throw new Error( + j$.formatErrorMsg('')( + `Can't spy on ${methodName} because assigning to it had no effect` + ) + ); + } + return spiedMethod; }; diff --git a/spec/core/SpyRegistrySpec.js b/spec/core/SpyRegistrySpec.js index eb20bebd..391a3d63 100644 --- a/spec/core/SpyRegistrySpec.js +++ b/spec/core/SpyRegistrySpec.js @@ -94,6 +94,30 @@ describe('SpyRegistry', function() { }).not.toThrowError(/is not declared writable or has no setter/); }); + it('throws if assigning to the property is a no-op', function() { + const scope = {}; + + function original() { + return 1; + } + + Object.defineProperty(scope, 'myFunc', { + get() { + return original; + }, + set() {} + }); + + const spyRegistry = new jasmineUnderTest.SpyRegistry({ + createSpy: createSpy + }); + expect(function() { + spyRegistry.spyOn(scope, 'myFunc'); + }).toThrowError( + " : Can't spy on myFunc because assigning to it had no effect" + ); + }); + it('overrides the method on the object and returns the spy', function() { const originalFunctionWasCalled = false, spyRegistry = new jasmineUnderTest.SpyRegistry({ diff --git a/src/core/SpyRegistry.js b/src/core/SpyRegistry.js index ff8da7e5..ba129924 100644 --- a/src/core/SpyRegistry.js +++ b/src/core/SpyRegistry.js @@ -84,6 +84,16 @@ getJasmineRequireObj().SpyRegistry = function(j$) { obj[methodName] = spiedMethod; + // Check if setting the property actually worked. Some objects, such as + // localStorage in Firefox and later Safari versions, have no-op setters. + if (obj[methodName] !== spiedMethod) { + throw new Error( + j$.formatErrorMsg('')( + `Can't spy on ${methodName} because assigning to it had no effect` + ) + ); + } + return spiedMethod; };