Spies and carrying over Function Properties

45 views
Skip to first unread message

Jasmine Hegman

unread,
May 1, 2013, 2:37:04 PM5/1/13
to jasmi...@googlegroups.com
Hey there, I have an interesting issue I discovered recently using a technique that I don't see used too often.

Essentially, because functions in JS are also first class objects, they can given properties. I wrote a component which uses this to hold its default options, and was surprised when it broke during a test. I could have made the spy not call through, but in this particular case I wanted it to. Inside the code, it tried to reference a function which was now spied, and the property did not exist, giving an error.

My fix was to store the default options object in a local variable in the test before spying, and then re-adding it to the function (now a spy wrapping function) after. This worked fine.

Anyway, I was just thinking and it may (or may not) be desirable to have a way to cause a spy to iterate over the function its going to spy on's properties and copy them over to make cases like this easier. I could see it being a performance hit, so maybe it should be a flag that can be passed to the spy functions?

Just food for though! Here's a really contrived example, but should illustrate the issue (I know it will look like there's better ways to do it, esp. with the fake object, its just simplified for illustration):


    it('wobbles', function() {

        // Pretend this source code to be tested
        var someObj = {
            someFunc: function() {
                return this.someFunc.stuff;
            }
        };
        someObj.someFunc.stuff = 'wheee';

        // Pretend this is the spec
        expect( someObj.someFunc() ).toBe('wheee'); // This will pass

        var stuffTemp = someObj.someFunc.stuff;

        spyOn(someObj, 'someFunc' ).andCallThrough();

        // someObj.someFunc.stuff = stuffTemp; // Try uncommenting this line and see the difference

        expect( someObj.someFunc() ).toBe('wheee'); // This will fail unless previous line is uncommented

        expect( someObj.someFunc ).toHaveBeenCalled(); // This will pass

    });

So yeah, this may not be a good enough of a use case to justify handling it, but I thought I'd bring it up since it is perfectly valid JavaScript (even if the inner function has to be tightly coupled with its function name since they took away arguments.callee)


Davis W. Frank

unread,
May 3, 2013, 12:52:14 AM5/3/13
to jasmi...@googlegroups.com
We're definitely going to make spies less intrusive in 2.0. We've not gotten to the code yet. 

But thanks for this feedback - this will help our design.

Thanks for using Jasmine and helping us make it better.

--dwf




--
You received this message because you are subscribed to the Google Groups "Jasmine" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jasmine-js+...@googlegroups.com.
To post to this group, send email to jasmi...@googlegroups.com.
Visit this group at http://groups.google.com/group/jasmine-js?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
 
 



--
thx,
--dwf
Reply all
Reply to author
Forward
0 new messages