2016-07-13 9 views
1

함수로 내 보낸 서비스 모듈이 있습니다. 구성 객체와 같이 몇 가지를 전달해야하므로이 구조를 유지해야합니다. 나는 서비스에서 기능을 빼내려고 노력하고 있지만 그것을 이해할 수는 없다. 내 응용 프로그램에서 테스트하는 동안 문제가되는 API 호출을 만드는 함수가 있으므로 그것을 스텁 싶습니다. 이상 작동하지 않습니다sinon을 사용하여 함수로 내 보낸 노드 모듈의 함수/속성을 조롱하려면 어떻게해야합니까?

// 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'; 
    } 
}; 

는 그러나 다시, 나는 모듈에 정보를 전달 할 수 있어야합니다. 그런 방식으로 내보내는 모듈에서 함수를 스텁 (stub)하는 방법이 있습니까? 나는 또한 프록시 쿠어를 찾고 있었지만 그 대답인지 확실하지 않았다.

답변

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; 
    } 
} 

이제 모듈을 안전하게 스터브 할 수 있습니다.

그러나 스터 빙하는 방법은 안전하지 않은 것으로 간주해야합니다. 테스트가 완벽하게 작동하면 스텁이 정리됩니다.

// 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); 
    }); 
}); 

은 의존성 주입을 사용하여 종속성을 스텁 할 수있는 다른 옵션이 있습니다 : 당신은 항상 같은 beforeafter (또는 beforeEachafterEach) 비품 내에서 스텁한다. https://github.com/vkarpov15/wagner-core 또는 내 것을 https://github.com/CaptEmulation/service-builder

+0

고맙습니다. 감사합니다. 나는 TDD에 뛰어 들기 위해 더 나은 습관을 만들려고 노력하고 있으며 이것은 분명 도움이 될 것입니다. 내가 제안한대로 함수를 정적으로 노출합니다. 스텁을 청소 해 주셔서 감사합니다. 나는 청소를하기 위해 달리고있는 afterEach를한다 :) 나는 나의 질문에 그것을 포함해야했다라고 생각한다! – ahnkee

+0

그것이 작동한다면 내 대답을 수락하는 것을 고려하십시오 – CaptEmulation

+0

그냥 했어요. 내 이전 의견을 마무리하는 중간에 : p – ahnkee