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?
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?
Share Improve this question asked Oct 18, 2012 at 22:50 h2steinh2stein 6164 silver badges14 bronze badges2 Answers
Reset to default 3Jasmine 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.
Sometimes if your unit tests are hard to get right, it's telling you the code needs to be more unit-y, and there's probably some method that has too many responsibilities. Looks like myCode
is doing a couple different things: applying callback
to some array, and then modifying that array. Perhaps the code that modifies the array can be extracted into its own method which myCode
calls. Then you can simply stub out that extra method in the unit test which ensures that the callback is being called with the right arguments.
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745078170a4609959.html
评论列表(0条)