[Finishes #52959947] Warn user about spy conflicts; Refactor spy tests to more reflect responsibilities and removed duplicate tests
This commit is contained in:
@@ -27,6 +27,85 @@ describe("Env", function() {
|
||||
expect(fakeReporter.jasmineStarted).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
it('removes all spies when env is executed', function(done) {
|
||||
originalFoo = function() {},
|
||||
testObj = {
|
||||
foo: originalFoo
|
||||
},
|
||||
firstSpec = jasmine.createSpy('firstSpec').and.callFake(function() {
|
||||
env.spyOn(testObj, 'foo');
|
||||
}),
|
||||
secondSpec = jasmine.createSpy('secondSpec').and.callFake(function() {
|
||||
expect(testObj.foo).toBe(originalFoo);
|
||||
});
|
||||
env.describe('test suite', function() {
|
||||
env.it('spec 0', firstSpec);
|
||||
env.it('spec 1', secondSpec);
|
||||
});
|
||||
|
||||
var assertions = function() {
|
||||
expect(firstSpec).toHaveBeenCalled();
|
||||
expect(secondSpec).toHaveBeenCalled();
|
||||
done();
|
||||
};
|
||||
|
||||
env.addReporter({ jasmineDone: assertions });
|
||||
|
||||
env.execute();
|
||||
});
|
||||
|
||||
describe("#spyOn", function() {
|
||||
it("checks for the existance of the object", function() {
|
||||
expect(function() {
|
||||
env.spyOn(void 0, 'pants');
|
||||
}).toThrowError(/could not find an object/);
|
||||
});
|
||||
|
||||
it("checks for the existance of the method", function() {
|
||||
var subject = {};
|
||||
|
||||
expect(function() {
|
||||
env.spyOn(subject, 'pants');
|
||||
}).toThrowError(/method does not exist/);
|
||||
});
|
||||
|
||||
it("checks if it has already been spied upon", function() {
|
||||
var subject = { spiedFunc: function() {} };
|
||||
|
||||
env.spyOn(subject, 'spiedFunc');
|
||||
|
||||
expect(function() {
|
||||
env.spyOn(subject, 'spiedFunc');
|
||||
}).toThrowError(/has already been spied upon/);
|
||||
});
|
||||
|
||||
it("overrides the method on the object and returns the spy", function() {
|
||||
var originalFunctionWasCalled = false;
|
||||
var subject = { spiedFunc: function() { originalFunctionWasCalled = true; } };
|
||||
|
||||
originalFunc = subject.spiedFunc;
|
||||
|
||||
var spy = env.spyOn(subject, 'spiedFunc');
|
||||
|
||||
expect(subject.spiedFunc).toEqual(spy);
|
||||
|
||||
expect(subject.spiedFunc.calls.any()).toEqual(false);
|
||||
expect(subject.spiedFunc.calls.count()).toEqual(0);
|
||||
|
||||
subject.spiedFunc('foo');
|
||||
|
||||
expect(subject.spiedFunc.calls.any()).toEqual(true);
|
||||
expect(subject.spiedFunc.calls.count()).toEqual(1);
|
||||
expect(subject.spiedFunc.calls.mostRecent().args).toEqual(['foo']);
|
||||
expect(subject.spiedFunc.calls.mostRecent().object).toEqual(subject);
|
||||
expect(originalFunctionWasCalled).toEqual(false);
|
||||
|
||||
subject.spiedFunc('bar');
|
||||
expect(subject.spiedFunc.calls.count()).toEqual(2);
|
||||
expect(subject.spiedFunc.calls.mostRecent().args).toEqual(['bar']);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#catchException", function() {
|
||||
it("returns true if the exception is a pending spec exception", function() {
|
||||
|
||||
@@ -1,210 +1,31 @@
|
||||
describe('Spies', function () {
|
||||
var env;
|
||||
beforeEach(function() {
|
||||
env = new j$.Env();
|
||||
});
|
||||
describe("createSpy", function() {
|
||||
var TestClass;
|
||||
|
||||
it('should replace the specified function with a spy object', function() {
|
||||
var originalFunctionWasCalled = false;
|
||||
var TestClass = {
|
||||
someFunction: function() {
|
||||
originalFunctionWasCalled = true;
|
||||
}
|
||||
};
|
||||
env.spyOn(TestClass, 'someFunction');
|
||||
beforeEach(function() {
|
||||
TestClass = function() {};
|
||||
TestClass.prototype.someFunction = function() {};
|
||||
TestClass.prototype.someFunction.bob = "test";
|
||||
});
|
||||
|
||||
it("preserves the properties of the spied function", function() {
|
||||
var spy = j$.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
|
||||
|
||||
expect(TestClass.someFunction.calls.any()).toEqual(false);
|
||||
expect(TestClass.someFunction.calls.count()).toEqual(0);
|
||||
|
||||
TestClass.someFunction('foo');
|
||||
|
||||
expect(TestClass.someFunction.calls.any()).toEqual(true);
|
||||
expect(TestClass.someFunction.calls.count()).toEqual(1);
|
||||
expect(TestClass.someFunction.calls.mostRecent().args).toEqual(['foo']);
|
||||
expect(TestClass.someFunction.calls.mostRecent().object).toEqual(TestClass);
|
||||
expect(originalFunctionWasCalled).toEqual(false);
|
||||
|
||||
TestClass.someFunction('bar');
|
||||
expect(TestClass.someFunction.calls.count()).toEqual(2);
|
||||
expect(TestClass.someFunction.calls.mostRecent().args).toEqual(['bar']);
|
||||
});
|
||||
|
||||
it('should allow you to view args for a particular call', function() {
|
||||
var originalFunctionWasCalled = false;
|
||||
var TestClass = {
|
||||
someFunction: function() {
|
||||
originalFunctionWasCalled = true;
|
||||
}
|
||||
};
|
||||
env.spyOn(TestClass, 'someFunction');
|
||||
|
||||
TestClass.someFunction('foo');
|
||||
TestClass.someFunction('bar');
|
||||
expect(TestClass.someFunction.calls.first().args).toEqual(['foo']);
|
||||
expect(TestClass.someFunction.calls.mostRecent().args).toEqual(['bar']);
|
||||
});
|
||||
|
||||
it('should be possible to call through to the original method, or return a specific result', function() {
|
||||
var originalFunctionWasCalled = false;
|
||||
var passedArgs;
|
||||
var passedObj;
|
||||
var TestClass = {
|
||||
someFunction: function() {
|
||||
originalFunctionWasCalled = true;
|
||||
passedArgs = Array.prototype.slice.call(arguments, 0);
|
||||
passedObj = this;
|
||||
return "return value from original function";
|
||||
}
|
||||
};
|
||||
|
||||
env.spyOn(TestClass, 'someFunction').and.callThrough();
|
||||
var result = TestClass.someFunction('arg1', 'arg2');
|
||||
expect(result).toEqual("return value from original function");
|
||||
expect(originalFunctionWasCalled).toEqual(true);
|
||||
expect(passedArgs).toEqual(['arg1', 'arg2']);
|
||||
expect(passedObj).toEqual(TestClass);
|
||||
expect(TestClass.someFunction.calls.any()).toEqual(true);
|
||||
});
|
||||
|
||||
it('should be possible to return a specific value', function() {
|
||||
var originalFunctionWasCalled = false;
|
||||
var TestClass = {
|
||||
someFunction: function() {
|
||||
originalFunctionWasCalled = true;
|
||||
return "return value from original function";
|
||||
}
|
||||
};
|
||||
|
||||
env.spyOn(TestClass, 'someFunction').and.callReturn("some value");
|
||||
originalFunctionWasCalled = false;
|
||||
var result = TestClass.someFunction('arg1', 'arg2');
|
||||
expect(result).toEqual("some value");
|
||||
expect(originalFunctionWasCalled).toEqual(false);
|
||||
});
|
||||
|
||||
it('should be possible to throw a specific error', function() {
|
||||
var originalFunctionWasCalled = false;
|
||||
var TestClass = {
|
||||
someFunction: function() {
|
||||
originalFunctionWasCalled = true;
|
||||
return "return value from original function";
|
||||
}
|
||||
};
|
||||
|
||||
env.spyOn(TestClass, 'someFunction').and.callThrow(new Error('fake error'));
|
||||
var exception;
|
||||
try {
|
||||
TestClass.someFunction('arg1', 'arg2');
|
||||
} catch (e) {
|
||||
exception = e;
|
||||
}
|
||||
expect(exception.message).toEqual('fake error');
|
||||
expect(originalFunctionWasCalled).toEqual(false);
|
||||
});
|
||||
|
||||
it('should be possible to call a specified function', function() {
|
||||
var originalFunctionWasCalled = false;
|
||||
var fakeFunctionWasCalled = false;
|
||||
var passedArgs;
|
||||
var passedObj;
|
||||
var TestClass = {
|
||||
someFunction: function() {
|
||||
originalFunctionWasCalled = true;
|
||||
return "return value from original function";
|
||||
}
|
||||
};
|
||||
|
||||
env.spyOn(TestClass, 'someFunction').and.callFake(function() {
|
||||
fakeFunctionWasCalled = true;
|
||||
passedArgs = Array.prototype.slice.call(arguments, 0);
|
||||
passedObj = this;
|
||||
return "return value from fake function";
|
||||
expect(spy.bob).toEqual("test");
|
||||
});
|
||||
|
||||
var result = TestClass.someFunction('arg1', 'arg2');
|
||||
expect(result).toEqual("return value from fake function");
|
||||
expect(originalFunctionWasCalled).toEqual(false);
|
||||
expect(fakeFunctionWasCalled).toEqual(true);
|
||||
expect(passedArgs).toEqual(['arg1', 'arg2']);
|
||||
expect(passedObj).toEqual(TestClass);
|
||||
expect(TestClass.someFunction.calls.any()).toEqual(true);
|
||||
});
|
||||
|
||||
it('removes all spies when env is executed', function(done) {
|
||||
var env = new j$.Env(),
|
||||
originalFoo = function() {},
|
||||
testObj = {
|
||||
foo: originalFoo
|
||||
},
|
||||
firstSpec = jasmine.createSpy('firstSpec').and.callFake(function() {
|
||||
env.spyOn(testObj, 'foo');
|
||||
}),
|
||||
secondSpec = jasmine.createSpy('secondSpec').and.callFake(function() {
|
||||
expect(testObj.foo).toBe(originalFoo);
|
||||
});
|
||||
env.describe('test suite', function() {
|
||||
env.it('spec 0', firstSpec);
|
||||
env.it('spec 1', secondSpec);
|
||||
it("warns the user that we indend to overwrite an existing property", function() {
|
||||
expect(function() {
|
||||
j$.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
|
||||
}).toThrowError("Jasmine spies would overwrite the 'and' and 'calls' properties on the object being spied upon");
|
||||
});
|
||||
|
||||
var assertions = function() {
|
||||
expect(firstSpec).toHaveBeenCalled();
|
||||
expect(secondSpec).toHaveBeenCalled();
|
||||
done();
|
||||
};
|
||||
it("adds a spyStrategy and callTracker to the spy", function() {
|
||||
var spy = j$.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
|
||||
|
||||
env.addReporter({ jasmineDone: assertions });
|
||||
|
||||
env.execute();
|
||||
});
|
||||
|
||||
it('throws an exception when some method is spied on twice', function() {
|
||||
var TestClass = { someFunction: function() {
|
||||
} };
|
||||
env.spyOn(TestClass, 'someFunction');
|
||||
var exception;
|
||||
try {
|
||||
env.spyOn(TestClass, 'someFunction');
|
||||
} catch (e) {
|
||||
exception = e;
|
||||
}
|
||||
expect(exception).toBeDefined();
|
||||
});
|
||||
|
||||
it('to spy on an undefined method throws exception', function() {
|
||||
var TestClass = {
|
||||
someFunction : function() {
|
||||
}
|
||||
};
|
||||
function efunc() {
|
||||
env.spyOn(TestClass, 'someOtherFunction');
|
||||
}
|
||||
|
||||
expect(function() {
|
||||
efunc();
|
||||
}).toThrow('someOtherFunction() method does not exist');
|
||||
});
|
||||
|
||||
it('should be able to reset a spy', function() {
|
||||
var TestClass = { someFunction: function() {} };
|
||||
env.spyOn(TestClass, 'someFunction');
|
||||
|
||||
expect(TestClass.someFunction).not.toHaveBeenCalled();
|
||||
TestClass.someFunction();
|
||||
expect(TestClass.someFunction).toHaveBeenCalled();
|
||||
TestClass.someFunction.calls.reset();
|
||||
expect(TestClass.someFunction).not.toHaveBeenCalled();
|
||||
expect(TestClass.someFunction.calls.count()).toEqual(0);
|
||||
});
|
||||
|
||||
it("preserves the properties of the spied function", function() {
|
||||
var TestClass = function() {};
|
||||
TestClass.prototype.someFunction = function() {};
|
||||
TestClass.prototype.someFunction.bob = "test";
|
||||
|
||||
var spy = env.spyOn(TestClass.prototype, 'someFunction');
|
||||
|
||||
expect(spy.bob).toEqual("test");
|
||||
expect(spy.and).toEqual(jasmine.any(j$.SpyStrategy);
|
||||
expect(spy.calls).toEqual(jasmine.any(j$.CallTracker);
|
||||
});
|
||||
});
|
||||
|
||||
describe("createSpyObj", function() {
|
||||
|
||||
@@ -211,16 +211,16 @@ getJasmineRequireObj().Env = function(j$) {
|
||||
|
||||
this.spyOn = function(obj, methodName) {
|
||||
if (j$.util.isUndefined(obj)) {
|
||||
throw "spyOn could not find an object to spy upon for " + methodName + "()";
|
||||
throw new Error("spyOn could not find an object to spy upon for " + methodName + "()");
|
||||
}
|
||||
|
||||
if (j$.util.isUndefined(obj[methodName])) {
|
||||
throw methodName + '() method does not exist';
|
||||
throw new Error(methodName + '() method does not exist');
|
||||
}
|
||||
|
||||
if (obj[methodName] && j$.isSpy(obj[methodName])) {
|
||||
//TODO?: should this return the current spy? Downside: may cause user confusion about spy state
|
||||
throw methodName + ' has already been spied upon';
|
||||
throw new Error(methodName + ' has already been spied upon');
|
||||
}
|
||||
|
||||
var spy = j$.createSpy(methodName, obj[methodName]);
|
||||
|
||||
@@ -65,13 +65,17 @@ getJasmineRequireObj().base = function(j$) {
|
||||
return spyStrategy.exec.apply(this, arguments);
|
||||
};
|
||||
|
||||
spy.and = spyStrategy;
|
||||
spy.calls = callTracker;
|
||||
for (var prop in originalFn) {
|
||||
if (prop === 'and' || prop === 'calls') {
|
||||
throw new Error("Jasmine spies would overwrite the 'and' and 'calls' properties on the object being spied upon");
|
||||
}
|
||||
|
||||
for (prop in originalFn) {
|
||||
spy[prop] = originalFn[prop];
|
||||
}
|
||||
|
||||
spy.and = spyStrategy;
|
||||
spy.calls = callTracker;
|
||||
|
||||
return spy;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user