Reputation: 6846
I'm just getting started with Jasmine and trying to set up some tests for the first time. I have a Backbone collection. I figured I would get my collection as part of the beforeEach() method, then perform tests against it.
I have a test json object that I used while I prototyped my app, so rather than mocking an call, I'd prefer to reuse that object for testing.
Here's my code so far (and it is failing).
describe("Vehicle collection", function() {
beforeEach(function() {
this.vehicleCollection = new Incentives.VehiclesCollection();
this.vehicleCollection.url = '../../json/20121029.json';
this.vehicleCollection.fetch();
console.log(this.vehicleCollection);
});
it("should contain models", function() {
expect(this.vehicleCollection.length).toEqual(36);
console.log(this.vehicleCollection.length); // returns 0
});
});
When I console.log in the beforeEach method -- the console look like this ...
d {length: 0, models: Array[0], _byId: Object, _byCid: Object, url: "../../json/20121029.json"}
Curiously when I expand the object (small triangle) in Chrome Developer Tools -- my collection is completely populated with an Array of vehicle models, etc. But still my test fails:
Error: Expected 0 to equal 36
I'm wondering if I need to leverage the "waitsFor()" method?
UPDATE (with working code)
Thanks for the help!
@deven98602 -- you got me on the right track. Ultimately, this "waitsFor()" implementation finally worked. I hope this code helps others! Leave comments if this is a poor technique. Thanks!
describe("A Vehicle collection", function() {
it("should contain models", function() {
var result;
var vehicleCollection = new Incentives.VehiclesCollection();
vehicleCollection.url = '/json/20121029.json';
getCollection();
waitsFor(function() {
return result === true;
}, "to retrive all vehicles from json", 3000);
runs(function() {
expect(vehicleCollection.length).toEqual(36);
});
function getCollection() {
vehicleCollection.fetch({
success : function(){
result = true;
},
error : function () {
result = false;
}
});
}
});
});
Upvotes: 2
Views: 1437
Reputation: 27374
Just glancing at your code, it looks to me like fetch
has not yet populated the collection when you run the expectation.
You can use the return value from fetch
to defer the expectation until the response is received using waitsFor
and runs
:
beforeEach(function() {
this.vehicleCollection = new Incentives.VehiclesCollection();
this.vehicleCollection.url = '../../json/20121029.json';
var deferred = this.vehicleCollection.fetch();
waitsFor(function() { return deferred.done() && true });
});
it("should contain models", function() {
runs(function() {
expect(this.vehicleCollection.length).toEqual(36);
});
});
I haven't actually tried this can't guarantee that it will work as-is, but the solution will look something like this. See this article for more on asynchronous testing with Jasmine.
Upvotes: 2
Reputation: 1110
the collection.fetch() is asyn call that accepts success and error callbacks
var result;
this.collection.fetch({success : function(){
result = true;
}})
waitsFor(function() {
return response !== undefined;
}, 'must be set to true', 1000);
runs(function() {
expect(this.vehicleCollection.length).toEqual(36);
console.log(this.vehicleCollection.length); // returns 0
});
Upvotes: 1