nonlogos
12/15/2017 - 9:42 PM

Unit testing suing Sinon

Unit testing suing Sinon

/* Come with all the functionality of spies, but they replace the target function
** they have methods that can add custom behaviors including:
**  * returning a specific value
**  * throwing a specific exception
**  * automatically invoking callbacks with provided arguments
**  * defining behavior on nth call to stub
**
** some common use cases include:
** * Replace AJAX calls to prevent database calls
** * Trigger different code paths depending on funciton output
** * Testing output when a particular exception is thrown
*/

// example code
function saveUser(user, callback) {
  jquery.post('/users', {
    first: user.firstname,
    last: user.lastname
  }, callback);
}

// test code

describe('saveUser', () => {
  it('should call back after saving', () => {
    let post = sinon.stub(jquery, 'post') // prevent sending the post request
    post.yields() // make the stub call the 1st callback it receives
    let callbackSpy = sinon.spy() // use a spy as callback
    let testUser = { firstname: 'Severus', lastname: 'Snape' };
    saveUser(testUser, callbackSpy);
    
    expect(callbackSpy).to.have.been.calledOnce;
    
    post.restore();
  })
})






// only spies on the function but does not change its behavior

// SPY: basic anonymous spy example

function testMe(callback) {
  callback();
}

// testing function
describe('testMe funciton', () => {
  it('should call the callback', ()=> {
    let callbackSpy = sinon.spy(); // anonymous spy
    testMe(callbackSpy);
    expect(callbackSpy).to.have.been.calledOnce;
    
    callbackSpy.restore();
  })
})

// SPY: wrap an existing method

const user = {
  // ...
  setName: function(name) {
    this.name = name;
  }
}

// testing function

describe('setName function', () => {
  it('should be called with name', () => {
    let setNameSpy = sinon.spy(user, 'setName');
    
    user.setName('Harry Potter');
    
    expect(setNameSpy).to.have.been.calledOnce;
    expect(setNameSpy).to.have.been.calledWith('Harry Potter');
  
    // important! Remove the spy at end to prevent future errors
    setNameSpy.restore();
  })
})