Correctly teardown spies on inherited methods

- If the spied method is not an own property of the object being spied
  upon, the method is deleted from the object on teardown instead of
  being set to the original implementation.

- #737
This commit is contained in:
Ben Christel
2016-02-01 17:45:47 -08:00
parent e0541eca80
commit d6f1f8dec5
2 changed files with 34 additions and 8 deletions

View File

@@ -89,5 +89,22 @@ describe("SpyRegistry", function() {
expect(subject.spiedFunc).toBe(originalFunction);
});
it("does not add a property that the spied-upon object didn't originally have", function() {
var spies = [],
spyRegistry = new jasmineUnderTest.SpyRegistry({currentSpies: function() { return spies; }}),
originalFunction = function() {},
subjectParent = {spiedFunc: originalFunction};
var subject = Object.create(subjectParent);
expect(subject.hasOwnProperty('spiedFunc')).toBe(false);
spyRegistry.spyOn(subject, 'spiedFunc');
spyRegistry.clearSpies();
expect(subject.hasOwnProperty('spiedFunc')).toBe(false);
expect(subject.spiedFunc).toBe(originalFunction);
})
});
});

View File

@@ -33,25 +33,34 @@ getJasmineRequireObj().SpyRegistry = function(j$) {
throw new Error(methodName + ' is not declared writable or has no setter');
}
var spy = j$.createSpy(methodName, obj[methodName]);
var originalMethod = obj[methodName],
spiedMethod = j$.createSpy(methodName, originalMethod),
restoreStrategy;
if (Object.prototype.hasOwnProperty.call(obj, methodName)) {
restoreStrategy = function() {
obj[methodName] = originalMethod;
};
} else {
restoreStrategy = function() {
delete obj[methodName];
};
}
currentSpies().push({
spy: spy,
baseObj: obj,
methodName: methodName,
originalValue: obj[methodName]
restoreObjectToOriginalState: restoreStrategy
});
obj[methodName] = spy;
obj[methodName] = spiedMethod;
return spy;
return spiedMethod;
};
this.clearSpies = function() {
var spies = currentSpies();
for (var i = 0; i < spies.length; i++) {
var spyEntry = spies[i];
spyEntry.baseObj[spyEntry.methodName] = spyEntry.originalValue;
spyEntry.restoreObjectToOriginalState();
}
};
}