I have some code which calls a callback function with an array as single argument. After calling the callback, the code changes the array contents. It is similar to this code:
function myCode( callback ) {
var someArray = [ 1, 2, 3, 4 ];
callback( someArray );
// change someArray in arbitrary ways
someArray.splice( 2 );
...
}
Now, I want to verify that the callback is called with the correct array content. Using Jasmine.js I would write my spec like this:
describe( "My code", function() {
var callback;
beforeEach( function() {
callback = jasmine.createSpy( "My callback" );
myCode( callback );
});
it( "calls the callback and passes the correct array", function() {
expect( callback ).toHaveBeenCalledWith( [ 1, 2, 3, 4 ] );
});
});
This fails. The problem is, that Jasmine.js records the array but does not make a copy of it. Since the array is changed after the call, the expect()-Line fails, even though the actual call fulfilled the expectation. The same problem occurs with mutable objects.
How can I test such code?
Jasmine does shallow copy the arguments
passed on to the spy, which mean the arguments
object will have reference to the same objects with which it has been called (in your case arguments
will have the reference to someArray
object only.
Jasmine code reference for spy implementation:
spy = function() {
callTracker.track({
object: this,
args: Array.prototype.slice.apply(arguments)
});
return spyStrategy.exec.apply(this, arguments);
};
Deep copy of array (arguments
) is not possible as a generic solution, problems are explained at link.
A solution to your problem could be writing your own callback and matcher for your specific use case, where you know what you have to copy (clone) exactly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With