8

I'm using the superagent ajax library for an app, and I'm trying to write some unit tests for it. I've got a class which looks like this:

someClass = {
  getData: function(){
    _this = this;
    superagent.get('/some_url').end(function(res){
      if(res.body){
        _this.data = res.body
      }
     });
   });
 }

How do I write a Jasmine test to spy on the _this.data = res.body call? Setting up a spy with and.callThrough() on getData isn't working. I don't want to actually call the URL in question; I'm just trying to test that if it gets data, it does something with it.

Thanks

Kevin Whitaker
  • 12,435
  • 12
  • 51
  • 89
  • 1
    I'd like to point out that the title sounds like a question that some innocent young agent would ask as they try to figure out what some 00's mission is. Presumably, they named their microdrone Jasmine. – Nic Dec 18 '14 at 19:34

4 Answers4

3
spyOn(superagent, 'get').and.callFake(function(url) {
  return {
    end: function(cb) {
      //null for no error, and object to mirror how a response would look.
      cb(null, {body: data});
    }
  }
});
Bror
  • 1,395
  • 9
  • 9
0

Bror's answer works perfectly. To add something to his answer, when we need to add another superagent function (like set) to the spyOn method, you can use as follows.

spyOn(superagent, 'get').and.callFake(function(url) {
  return {
      set: function() {
        return {
          end: function(cb) {
            //null for no error, and object to mirror how a response would look.
            cb(null, {body: data});
          }
        }
     }
});

Here, the set function is used to set headers to the request.

udayanga
  • 411
  • 4
  • 12
  • 1
    If we chain multiple methods like `get().query().headers().timeout().end()`, how do we spy on the inner most `get` call? Create a chain like the one you showed in the answer? – Salman Oct 08 '15 at 06:04
0

There's another good solution here, which is to abstract out the anonymous function:

someClass = {
  getData: function(){
    _this = this;
    superagent.get('/some_url').end(this.handleAjax);
  },

  handleAjax: function(res){
    if(res.body){
      _this.data = res.body
    }
  }
}

Now you can test the handleAjax function discretely and with simple tests; and also stub superagent as you only need to check a method .end() is called on it with a particular value.

Anonymous functions are problematic for other reasons than just testing so this is a good refactor

Toni Leigh
  • 4,830
  • 3
  • 22
  • 36
0

Say it's a patch, first make a mock patch return value:

this.mockPatchObject = {
      set: () => {
        return {
          end: (cb: any) => {
            cb(null, {body: 'etc'});
          },
        };
      },
    };

then return it as the value of patch:

this.superagentSpy = spyOn(request,'patch').and.returnValue(this.mockPatchObject);

then spy on the set function of the "mock" patch object:

this.superagentSetSpy = spyOn(this.mockPatchObject, 'set');
FlavorScape
  • 13,301
  • 12
  • 75
  • 117