2016-07-13 8 views
1

У меня есть сервисный модуль, который экспортируется как функция. Мне нужно передать пару вещей, как объект конфигурации, поэтому нужно сохранить эту структуру. Я пытаюсь отключить функцию из службы, но не могу понять это. В моем приложении у меня есть функция, которая вызывает вызов API, который является проблематичным во время тестирования, поэтому я хотел бы его заглушить. (Я понимаю, что я должен был бы написать мой тест по-разному обрабатывать вопрос асинхронной)Как я могу высмеять функцию/свойство модуля узла, экспортированного как функцию, используя синус?

// myService.js 
module.exports = function(config) { 
    function foo() { 
    returns 'bar'; 
    } 

    return { 
    foo: foo 
    }; 
}; 

// test.js 
var config = require('../../config'); 
var request = require('supertest'); 
var chai = require('chai'); 
var expect = chai.expect; 
var sinon = require('sinon'); 
var myService = require('./myService.js')(config); 

describe('Simple test', function(done) { 
    it('should expect "something else", function(done) { 
    var stub = sinon.stub(myService, 'foo').returns('something else'); 

    request(server) // this object is passed into my test. I'm using Express 
     .get('/testRoute') 
     .expect(200) 
     .expect(function(res) { 
     expect(res.body).to.equal('something else'); 
     stub.restore(); 
     }) 
     .end(done); 
    }); 
}); 

* /testRoute I set up as a simple GET route that simply returns the value from myService.foo() 

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

module.exports = { 
    test: function() { 
    return 'something'; 
    } 
}; 

Но опять же, я должен быть в состоянии передать информацию к модулю, так что я хотел бы, чтобы мои модули в первоначальной структуре выше. Есть ли способ заглушить функцию из модуля, который экспортируется таким образом? Я также изучал proxyquire, но не уверен, что это ответ.

ответ

2

Причина, по которой ваш тестовый заглушка не работает, заключается в том, что функция foo создается каждый раз, когда вызывается инициализатор модуля. Как вы обнаружили, когда у вас есть статический метод в модуле, вы можете заглушить.

Существует множество решений этой проблемы - но самым простым является статический метод.

// myService.js 
module.exports = function(config) { 
    return { 
    foo: foo 
    }; 
}; 

var foo = module.exports.foo = function foo() { 
    return 'bar' 
} 

Это уродливое, но работает.

Что делать, если функция foo имеет замыкание на переменные внутри службы (поэтому она живет в инициализаторе службы). Затем, к сожалению, они должны быть явно переданы.

// myService.js 
module.exports = function(config) { 
    return { 
    foo: foo 
    }; 
}; 

var foo = module.exports.foo = function(config) { 
    return function foo() { 
    return config.bar; 
    } 
} 

Теперь вы можете безопасно заглушить модуль.

Однако, как вы обрубать следует считать небезопасным. Только если ваш тест работает отлично, то заглушка будет очищена. Вы всегда должны окурок в before и after (или beforeEach и afterEach) светильников, таких как:

// We are not configuring the module, so the call with config is not needed 
var myService = require('./myService.js'); 

describe('Simple test', function(done) { 
    beforeEach(function() { 
    // First example, above 
    this.myStub = sinon.stub(myService, foo).returns('something else'); 
    // Second example, above 
    this.myStub = sinon.stub(myService, foo).returns(function() { 
     returns 'something else'; 
    }); 
    }); 

    afterEach(function() { 
    this.myStub.restore(); 
    }); 

    it('should expect "something else", function(done) { 
    request(server) // this object is passed into my test. I'm using Express 
     .get('/testRoute') 
     .expect(200) 
     .expect(function(res) { 
     expect(res.body).to.equal('something else'); 
     }) 
     .end(done); 
    }); 
}); 

Есть и другие варианты, чтобы иметь возможность окурок зависимостей с помощью инъекции зависимостей. Я рекомендую посмотреть на https://github.com/vkarpov15/wagner-core или мой собственный https://github.com/CaptEmulation/service-builder

+0

Спасибо, это имеет смысл. Я пытаюсь погрузиться в TDD и строить лучшие привычки, и это, безусловно, поможет. Я стану подвергать функции статически, как вы предполагали. Благодарим вас за то, что вы подняли головку на очистку заглушки. Я делаю после того, как я бегу, чтобы очистить :) Думаю, я должен был включить его в мой вопрос! – ahnkee

+0

подумайте о принятии моего ответа, если он сработает для вас – CaptEmulation

+0

Просто сделал. Был в середине моего предыдущего комментария: p – ahnkee