Reputation: 41949
I have a BackboneView which I pass a collection upon creation
var my_collection = new Collection();
new MyView({temp: template, collection: my_collection });
Inside the view, the fetch() method is called on the collection in the constructor like this
export class MyView extends Backbone.View {
constructor(options){
this.collection = options.collection;
super();
this.collection.fetch().done(function(resp){
that.render();
})
}
render(){
}
}
I had (past tense) a series of tests that tested the UI/template of the View like this
describe('testing my view', function() {
it('should have one main child - div 6 ', function() {
expect(myview.el.children.length).to.equal(1);
});
});
However, since I have now added code that passed the collection to the view, and called the fetch method on the collection in the constructor, all of my tests fail because the view tries to call the fetch method every time I run the tests. Even if I pass a stub collection, I have to set a url
and the view will try to fetch on the stub collection resulting in a 404
var gs = class StubCollection extends Backbone.Collection{
constructor(options){
this.url = '/blah';
}
}
const drv = new MyView({temp: template, collection: new gs()});
I need to call fetch on the collection in the view (i.e. I can't not use that code). How can I continue to test the view in this situation?
Upvotes: 0
Views: 423
Reputation: 4583
Not the easiest solution, but in the long term definitely the best:
You shouldn't call fetch
on a collection from a view.
A view really has no business telling a collection or model what to do. A view only presents data and/or captures user input. The call for loading said data should be someplace else. Depending on what paradigm you like to follow this could be in a controller or command. It will make testing a lot easier, since your views will be more system agnostic, i.e. they have less knowledge of what's happening when. Views, models, collections and services should always be as dumb as possible: it's easier to test, reuse, extend and modify. All application-specific code should go into your controllers and commands. I.e. they are the glue that combine your application agnostic views, models and services into the specific application your working on.
Upvotes: 2
Reputation: 741
You can stub the fetch
method itself. Inside StubCollection
define it as:
function fetch() {
return $.Deferred().resolve().promise();
}
According to the Backbone's documentation, fetch
returns a jqXHR which represents the request that is sent.
jqXHR is a Promise, which is an object that represents an ongoing process that may either succeed or fail, and has methods called done
and fail
for registering callbacks to be called when it succeeds or fails, respectively. (jqXHR succeeds if the request is successful and fails it could not be sent or the server returned an error code).
In the above code, we manually create a Deferred object (used to create promises), and immediately change its state to successful (with resolve
). Then we return its promise. Because the promise is immediately considered successful, the done
callback will be called immediately.
Upvotes: 3