2016-11-30 7 views
3

У меня есть простая функция, такая как;Sinon to unit test 'catch' statement

module.exports = { 
    fetchUser:function(myUserId) { 
    return new Promise((resolve, reject) => { 
     this.getUser(myUserId) 
     .then(user => { 
      // do logic // then return user 

      return user; 
     }) 
     .then(resolve) 
     .catch(err => { 
      // whoops there has been an error 

      let error = { error: 'My Error' }; 

      reject(error); 
     }); 
    }); 
    } 
}; 

Я хочу модульного тестирования как результат resolve и reject.

Простой тест chai будет;

var expect = require('chai').expect; 
var user = require('./user'); 

describe('User module', function() { 
    it('test fetchUser', function() { 
    let _user = user.fetchUser('abc123'); 

    return _user 
     .then(user => { 
     expect(data).to.be.an('object'); 
     }); 
    }); 

sinon Используя или другую библиотеку, как я могу для функции fetchUser бросить эту reject ошибку?

ответ

3

С Мокко, Chai и Sinon он может быть реализован с погасил методом getUser.

const User = require("./fetchUserModule"); 

describe('User module',() => { 
    beforeEach(() => User.getUser = sinon.stub()); 

    afterEach(() => User.getUser.reset()); 

    it('returns user if `getUser` returns data',() => { 
     const user = {name: 'John'}; 
     User.getUser.withArgs("abc123").returns(Promise.resolve(user)); 

     return User.fetchUser("abc123").then(result => { 
      expect(result).to.equal(user) 
     }).catch(error => { 
      expect(error).to.be.undefined; 
     }) 
    }); 

    it('throws error if `getUser` is rejected',() => { 
     User.getUser.withArgs("abc123").returns(Promise.reject()); 

     return User.fetchUser("abc123").then(result => { 
      expect(result).to.be.undefined; 
     }).catch(err => { 
      expect(err).to.eql({error: 'My Error'}) 
     }) 
    }); 
}); 
+0

Спасибо. Если я настрою тест таким образом, он на самом деле никогда не вводит мой код catch? Заглушка просто подделывает ответ, чтобы соответствовать ошибке, выброшенной из моего улова. – sketchthat

+2

Да, он входит в оператор 'catch', поскольку ошибка равна' {error: 'My Error'} '. Что вам нужно больше, чтобы доказать, что он работает? –

+0

Спасибо, я просто проверял, я еще не совсем понял заглушки. Я проверю это. – sketchthat

1

Начните с чего-нибудь в вашей «логике», которая может вызвать ошибку.

Если нет, вам нужно будет заглушить this.getUser, чтобы отклонить или выбросить ошибку вместо возврата данных. sinon-as-promised исправления sinon.stub, чтобы включить .resolves и .rejects обещание помощников.

const sinon = require('sinon') 
require('sinon-as-promised') 

Установка заглушки для испытаний на отказ.

before(function(){ 
    sinon.stub(user, 'getUser').rejects(new Error('whatever')) 
}) 

after(function(){ 
    user.getUser.restore() 
}) 

Тогда либо поймать ошибку .fetchUser или использовать chai-as-promised для некоторого сахара.

it('test fetchUser', function() { 
    return user.fetchUser('abc123') 
    .then(()=> expect.fail('fetchUser should be rejected')) 
    .catch(err => { 
     expect(err.message).to.eql('whatever') 
    }) 
}) 

it('test fetchUser', function() { 
    return expect(user.fetchUser('abc123')).to.be.rejectedWith(Error) 
}) 

или async, если вы живете в новом мире

it('test fetchUser', async function() { 
    try { 
    await user.fetchUser('abc123') 
    expect.fail('fetchUser should be rejected')) 
    } catch(err) { 
    expect(err.message).to.eql('whatever') 
    } 
}) 

Как примечание стороны, вам не нужно обернуть то, что уже возвращает обещание в new Promise и быть осторожным о потере информации об ошибках при соединении нескольких обработчиков .catch.

fetchUser: function (myUserId) { 
    return this.getUser(myUserId) 
    .then(user => { 
     //logic 
     return user 
    }) 
    .catch(err => { 
     let error = new Error('My Error') 
     error.original = err 
     reject(error) 
    }); 
} 
+0

Thanks Matt. Я не понимал, что последний момент, я буду обновлять свою кодовую базу. – sketchthat