I've got a function whose output I want to mess with. It's a little like a combination of andCallThrough and andCallFake. For example, suppose I've got this constructor function:
function Widget() {
this.frobble = function() {return 1;};
}
function frotz() {
return new Widget().frobble();
}
What I want to be able to do is something like this:
describe("Widget", function() {
it("is created and frobbled when frotz() is called", function() {
var widget;
spyOn(window, 'Widget').andMessWithOutput(function(newWidget) {
widget = newWidget;
spyOn(widget, 'frobble').andCallThrough();
frotz();
expect(widget.frobble.calls.length).toBe(1);
});
});
});
The best way I've found for doing this is the following:
it("is clumsily created and frobbled when frotz() is called", function() {
var widget;
spyOn(window, 'Widget').andCallFake(function() {
// originalValue is the original spied-upon value. note that if it's a constructor
// you've got to call it with new (though that shouldn't seem unusual).
widget = new Widget.originalValue();
spyOn(widget, 'frobble').andCallThrough();
frotz();
expect(widget.frobble.calls.length).toBe(1);
});
});
I have a helper I use for this, maybe it could be useful to others.
// testUtils.js
module.exports = {
spyOn: customSpyOn
};
function customSpyOn(obj, name) {
const fn = obj[name];
return {
and: {
wrapWith: wrapWith
}
};
function wrapWith(wrapper) {
obj[name] = jasmine.createSpy(`wrapped: ${name}`)
.and.callFake(spyWrapper);
return obj[name];
function spyWrapper() {
const args = [].slice.call(arguments);
return wrapper.apply(obj, [fn].concat(args));
}
}
}
If you were wanting to add spies to the return value of;
const connection = socket.createConnection('ws://whatever.com/live', {
format: 'json'
});
connection.open();
// etc...
The top of your spec and setup might look something like this
// some.spec.js
const testUtils = require('./testUtils');
testUtils.spyOn(socket, 'createConnection')
.and
.wrapWith(function(original, url, options) {
var api = original(url, options);
spyOn(api, 'open').and.callThrough();
spyOn(api, 'close').and.callThrough();
spyOn(api, 'send').and.callThrough();
return api;
});
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.