Search code examples
javascriptbackbone.jssinonchaikarma-mocha

how to test a view that calls fetch on a collection in its constructor?


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 urland 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?


Solution

  • 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.