2016-02-15 4 views
1

У меня есть яваскрипт функция:Тестовых функций, которые требуют обещаний внутри них с мокко

var otherModule = require('../otherModule'); 

function myFn(req, res, next) { 

    otherModule.queryFunction() 
    .then(function(results) { 
     res.json(results); 
    }) 
    .catch(function(err)) { 
     res.json({ 
     err: err 
     }); 
    }); 
} 

Для того, чтобы проверить myFn функцию я издевался (с mockery) otherModule.queryFunction в моем тестовом модуле, так что возвращает некоторые известные результаты. В модуле myFn я хочу проверить, что вызывается res.json. Я знаю, если бы я тестировал otherModule.queryFunction, я мог бы это сделать, вернув обещание или передав аргумент done функции наблюдения. Но я не могу понять, как сделать асинхронный тест, если асинхронная часть находится внутри функции, вызванной тестируемой функцией.

Я попробовал этот подход без успеха:

'use strict'; 
var chai = require('chai'); 
var mockery = require('mockery'); 
var expect = chai.expect; 
var spies = require('chai-spies'); 
var myFn = require('path/to/myFn'); 
chai.use(spies); 

describe('myFn tests', function(){ 

    var otherModule; 
    var SOME_DATA = {data: 'hi'}; 
    beforeEach(function(){ 
    otherModule = { 
     queryFunction: function queryFunctionMock(){ 
     var promise = new Promise(function(resolve, reject){ 
      resolve(SOME_DATA); 
     }); 

     return promise; 
     } 
    }; 
    }); 

    beforeEach(function(){ 
    mockery.enable({ 
     warnOnReplace: false, 
     useCleanCache: true 
    }); 

    mockery.registerMock('../otherModule', otherModule); 
    }); 

    afterEach(function(){ 
    mockery.disable(); 
    }); 

    it('res.json should be called with otherModule.queryFunction results', function(){ 
    req = chai.spy(); 
    res = chai.spy.object(['json']); 
    next = chai.spy(); 

    myFn(req, res, next); 

    expect(res.json).to.have.been.called();  
    }); 
}); 
+0

Если ваш 'myFn' является асинхронным, он должен *' возвращать 'обещание *. Тогда вы можете легко подключиться к этому в своих тестах. – Bergi

+0

Я не могу этого сделать, потому что myFn является прямым промежуточным программным обеспечением (http://expressjs.com/ru/guide/writing-middleware.html), и он ничего не должен возвращать. – Carlos

+0

Экспресс действительно не заботится о возвращаемом значении, не так ли? – Bergi

ответ

1

Я думаю, единственное, что здесь не так, то, что вам нужно переместить требуют вашего тестируемого компонента, после вы инициализирован издевательство:

'use strict'; 
var chai = require('chai'); 
var mockery = require('mockery'); 
var expect = chai.expect; 
var spies = require('chai-spies'); 
var myFn; 
chai.use(spies); 

describe('myFn tests', function(){ 

    // [...] 

    beforeEach(function(){ 
    mockery.enable({ 
     warnOnReplace: false, 
     useCleanCache: true 
    }); 

    mockery.registerMock('../otherModule', otherModule); 

    // now load the component: 
    myFn = require('path/to/myFn'); 
    }); 
+0

Спасибо за ваш ответ. Он по-прежнему не работает, даже если мне требуется Fn после того, как mockery включен. – Carlos

+0

Thats weird. Я создал проект с использованием вашего кода, и я получаю сообщение об ошибке «ReferenceError: Promise не определено», что связано с тем, что для библиотеки обещаний нет (я полагаю). Но это показывает, что насмешка успешна. Вы получаете какую-либо ошибку? – Sonata

+0

Ты буйный, он работает. Я отказался от импортной точки при преобразовании моего первоначального варианта использования в этот пример. В некоторых тестах я переопределял 'otherModule.queryFunction', чтобы настроить поведение. Если я хочу это сделать, я должен отменить регистрацию и снова зарегистрировать фальшивку, потому что издевательский модуль - это не тот же экземпляр. Из-за этой ошибки конец теста не был достигнут, как я ожидал. – Carlos