2016-07-13 2 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'; 
    } 
}; 

また、モジュールに情報を渡す必要があるため、モジュールを上記の元の構造に保ちたいと思います。そのようにエクスポートするモジュールから関数をスタブする方法はありますか?私はプロキシクエストについても調べていましたが、それが答えなのかどうかはわかりません。

答えて

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

関連する問題