2017-02-22 18 views
2

У меня есть модуль (пример был упрощен), называемый process-prom, который имеет единственную функцию, которая принимает Promise как входную и обрабатывает ее - она ​​также вызывает другие функций с помощью модулей вне его следующим образом:Как проверить мой код async jasmine/nodejs/prom, используя Spies

//<process-promise.js> 
let User = require('user-module'); 

let processPromise = (promiseObj) => { 
     let user = new User(); 

     promiseObj.then((full_name) => { 
      const [ fname, sname ] = full_name.split(' '); 

      if (fname && sname) { 
       user.setDetails(fname, sname); 
      } else{ 
       console.log('nothing happened'); 
      } 

     }).catch((err) => { 
      console.log(err.message); 
     }); 
    }; 

module.exports = { 
processPromise 
}; 

Я пытаюсь модульного тестирования описанной выше функции, используя жасмин, ReWire и жасмин шпионов согласно следующим кодом

let rewire = require('rewire'); 
let mod = rewire('process-promise'); 

describe('process-promise module',() => { 

beforeEach(() => { 

    this.fakeUser = createSpyObj('fake-user', ['setDetails']); 
    this.fakeUserMod = jasmine.createSpy('fake-user-mod'); 
    this.fakeUserMod.and.returnValue(this.fakeUser) 

    this.revert = mod.__set__({ 
     User: this.fakeUserMod 
    }); 

}); 

    afterEach(() => { 
     this.revert(); 
    }); 


    it('fakeUser.setDetails should be called', (done) => { 
     mod.processPromise(Promise.resolve('user name')); 
     done(); 
     expect(this.fakeUser.setDetails).toHaveBeenCalledWith('user','name'); 
    }); 

}); 

Я ожидаю, что Spy this.fakeUser .setDetails следует вызвать, но я получаю сообщение от Jasmine «Ожидаемый шпион fake-user.setAll для вызова с ['user', 'name'], но он никогда не вызывался. " - проблема заключается в том, что обещание - это Async, но я включил проделанную функцию, как предлагали другие SO-вопросы, но это, похоже, не решает проблему для меня. В чем проблема с моим кодом? большинство других вопросов SO относятся к угловым, поэтому не помогают с моей проблемой.

ответ

1

Вы находитесь на правильном пути, обещание асинхронно, а затем функция done в вашем тесте вызывается до того, как обетование решит значение. Функция done используется в качестве обратного вызова, чтобы сообщить тестовому движку, что весь ваш асинхронный код завершен. Он должен быть вызван после того, как обещание разрешено к значению (или не удалось в этом отношении).

Для того, чтобы сделать это, вам нужно сделать следующие изменения в коде:

//<process-promise.js> 
let User = require('user-module'); 

let processPromise = (promiseObj) => { 
     let user = new User(); 

     // return a promise, to allow a client to chain a .then call 
     return promiseObj.then((full_name) => { 
      const [ fname, sname ] = full_name.split(' '); 

      if (fname && sname) { 
       user.setDetails(fname, sname); 
      } else{ 
       console.log('nothing happened'); 
      } 

     }).catch((err) => { 
      console.log(err.message); 
     }); 
    }; 

module.exports = { 
    processPromise 
}; 

тест будет выглядеть следующим образом:

it('fakeUser.setAll should be called', (done) => { 
     mod.processPromise(Promise.resolve('user name')).then(() => { 
      expect(this.fakeUser.setAll).toHaveBeenCalledWith('user','name'); 
      done(); 
     }).catch(done); 
    }); 

Обязательно добавьте .catch(done) , Это гарантирует, что ваш тест не удастся, если обещание разрешит ошибку.

+0

Большое вам спасибо за ваш быстрый и полезный ответ. изменения, которые вы предложили, отлично поработали, и это решило мою проблему с тестированием. – Dev

0

Возможно, что к моменту выполнения вашего тестового кода обещание не распространяется на код, находящийся в стадии тестирования. И просто называть done() не является магия синхронизации.

Я не знаком с rewire поэтому я поделюсь пример использования proxyquire

const proxyquire = require('proxyquire'); 

describe('process-promise module',() => { 
    const fakeUser = { setDetails: jasmine.createSpy('setDetails') }; 
    const fakeUserMod = jasmine.createSpy('fake-user-mod').and.returnValue(fakeUser); 
    const promiseObj = Promise.resolve('user name'); 

    beforeEach((done) => { 
     const processPromiseMod = proxyquire('process-promise', { 
      'user-module': fakeUserMod, 
     }); 

     processPromiseMod.processPromise(promiseObj); 

     promiseObj.then(() => done()); 
    }); 


    it('fakeUser.setDetails should be called',() => { 
     expect(fakeUser.setDetails).toHaveBeenCalledWith('user','name'); 
    }); 
}); 

Также отметим, что setAll не существует в экземпляре fakeUser. Думаю, вы имеете в виду setDetails вместо setAll.

+0

Привет, большое спасибо за предложение! Если бы я не разрешил его с помощью rewire, я бы определенно исследовал предложенный здесь метод proxyquire. – Dev