jsmocha
jsmocha copied to clipboard
Support for mocking new instances
I didn't see this mentioned in the docs so I've worked around it for now, but it would nice for jsmocha to support it natively. The workaround:
var saved = foo.bar.Constructor; var Temp = function() {}; foo.bar.Constructor.prototype = new Temp(); foo.bar.Constructor.prototype.expects('someMethod'); // call the code foo.bar.Constructor = saved;
The painful part is the save/restore, though it shouldn't really be all that necessary to create the Temp constructor either.
Maybe something like:
mock_object = {}; foo.bar.Constructor.new_instances(mock_object); mock_object.expects('someMethod'); // call the code
Hi,
I assume you're trying to mock a function for all instances of a class? Something like this...
var CoolThing = function(){};
CoolThing.prototype = {
say_hello: function(){
alert('hello world');
}
};
var really_cool_thing = new CoolThing();
var another_cool_thing = new CoolThing();
In this case mocking the prototype is the correct way to mock any instance of CoolThing's say_hello function, for example:
CoolThing.prototype.expects('say_hello');
Then calling either really_cool_thing.say_hello() or another_cool_thing.say_hello() would satisfy the expectation.
Not exactly, I want to mock a constructor to ensure that a fake object is returned (and code in the real constructor doesn't get executed).
Could you provide a code example to illustrate this. It's not clear what you're trying to do in the first example you gave.
On 9 Apr 2011, at 17:31, has207 [email protected] wrote:
Not exactly, I want to mock a constructor to ensure that a fake object is returned (and code in the real constructor doesn't get executed).
Reply to this email directly or view it on GitHub: https://github.com/kernow/jsmocha/issues/1#comment_977604
Let's say in my code I have a constructor that generates CoolThing objects:
var CoolThing = function() {
// call some expensive initialization code
};
var foo = new CoolThing();
After that all sorts of things are done to foo. So in my test I want to ensure that this constructor instead returns fake objects I can define in the test, and ensure foo is set to that object without calling the expensive init code.
Ignore the expects() bits in my previous example, that was just a distraction from the main issue. What I'd basically like to see is the ability to hook into the call to "new" and make it generate a fake object. It's not hard to do, as in my initial example, but annoying to save/restore the constructor function, and I think jsmocha can help here with some special syntax.
Ok, I understand you're wanting, to mock object constructors when new is called. This is something I've wanted to do in the past too. The problem is that new is a special JavaScript command and I don't know of a way to mock this in a way that would work properly, or even it it would be a desirable thing to do.
I've had a think about how to implement a way of mocking constructors, and something like this may be possible
var CoolThing = function() {
// call some expensive initialization code
};
// special call to mock out the constructor
new ConstructorMock(CoolThing);
// this would call the mock constructor rather than the actual constructor
var foo = new CoolThing();
ConstructorMock would do something like clone all of the class and prototype functions and properties of CoolThing onto a new mock object and replace CoolThing with this cloned object.
That sounds about right :)
You just also need a way to make the fake constructor return a custom object:
new ConstructorMock(CoolThing, object_to_instantiate);
Or something along those lines. Though I actually think adding a method to do this rather than baking it into the constructor for a ConstructorMock class would make for a better API, something along the lines of:
CoolThing.new_instances(object_to_instantiate);
That way you can also chain it just like the others, and attach expectations, arg matching etc:
CoolThing.passing(arg1, arg2).at_least(1).new_instances(object_to_instantiate);
I have something similar working in Python Flexmock if you want to take a look:
http://has207.github.com/flexmock/user-guide.html#override-new-method-on-a-class-and-return-fake-instances
I was thinking along the same lines. Maybe something like this...
// mocking
CoolThing.expects_new().passing(...).twice().returns('something');
// stubbing
CoolThing.stubs_new().passing(...).returns('something');
// spies
CoolThing.spies_new().passing(...).returns('something');
Or possibly CoolThing.expects_new_instance(), CoolThing.stubbs_new_instance() and CoolThing.spies_new_instance(). I believe there would still need to be a way to specify you want to mock a constructor which could be done with either:
new ConstructorMock(CoolThing);
// or
new Mock(CoolThing, { constructor: true });