2017-10-26 12 views
1

コード例Angularjsでテストごとに模擬サービスを変更するにはどうすればよいですか?

これはおそらく、より良いコードで説明されているので、私は以下の詳細、抽象化の例が含まれている - 私の質問はコメントで繰り返されます。

例の概要

例では、戻りコード200によってたとえば、あなたが合理的に複雑なモックサービスをモック、そして最初のテストでは、あなたが(一つの機能のための肯定的な結果を与えることをモックサービスをしたいです以下)。 2番目のテストでは、同じ関数が負の結果、たとえば500を返すようにしたいとします。

私は単純にプロバイダを挿入してメソッドを上書きできますが、正しい方法ですか?下記の「テスト2」を参照してください。

describe('CommentArea', function() { 

    var controller 
    beforeEach(function() { 
    module('app', function($provide) { 
     // Base mock definition 
     $provide.provider('comments', function() { 
     this.$get = function() { 
      return { 
      create: function() { 
       return new Promise(function(resolve) { 
       resolve({ code: 200 }) 
       }) 
      }, 
      delete: function() { 
       return new Promise(function(resolve) { 
       resolve({ code: 200 }) 
       }) 
      } 
      } 
     } 
     }) 
    }) 

    inject(function($componentController) { 
     controller = $componentController('CommentArea') 
    }) 
    }) 

    // Start tests 
    // 
    // Test 1 - Use the above mocked service "as is" - happy path scenario 
    // 
    it('appends comment when successful', function() { 
    expect(controller.commentCount).toEqual(0) 
    controller.create() // uses the comments service create method 
    expect(controller.commentCount).toEqual(1)  
    }) 

    // Test 2 - Use the above mocked service with a slight modification 
    // This time the create function will fail 
    // 
    it('does not append comment when unsuccessful', inject(function(comments) { 
    // overwrite for failure condition here 
    // QUESTION - is this acceptable? It seems odd just overwriting it 
    // so directly 
    comments.create = function() { 
     return new Promise(function(resolve) { 
     resolve({ code: 500 }) 
     }) 
    } 

    expect(controller.commentCount).toEqual(0) 
    controller.create() // uses the comments service create method 
    expect(controller.commentCount).toEqual(0)  
    })) 
}) 

答えて

1

通常、これは模倣された戻り値をbeforeEachに定義してはならないことを意味します。

な方法の一つは、機能が共通の関数スコープ(describeブロック)で定義されているローカル変数を返すようにすることです:

var createValue; 
... 
beforeEach(module('app', { comments: { 
    create: function() { return createValue }, ... 
})) 
... 
createValue = Promise.resolve(200); 
comments.create(); 

ローカル変数は、欠点を持っています。 createValueが誤って次のテストで再定義されなかった場合、テストは交差汚染される可能性があります。

さらに、このようなモックは重要なタスクを解決しません。嘲笑された機能はスパイされません。

beforeEach(function() { 
    module('app', { comments: jasmine.createSpyObj('comments', ['create', 'delete']) }); 
}); 

module新しいスパイオブジェクトは各beforeEach呼び出しで作成されることになっているので、この場合の機能でラップする必要があります。

これはまさにジャスミンのスパイを解決することになっている作業です。

は、戻り値は、その場で定義されています。

comment.create.and.returnValue(Promise.resolve(200)) 
comments.create(); 
+0

これは素晴らしいです - ちょうどそれを試してみましたが、それが動作します。私は完全に*理解していません - それで、私はそれを私の脳に落ち着かせるために数回上に行く必要があります。ありがとう! – Chris

+0

申し訳ありません - "関数でラップする必要がある"ことを明確にできますか? – Chris

+0

最初の例では 'beforeEach(module(..))'であり、 'beforeEach(function(){module(...)}'であることに注意してください。どちらも 'module'で動作しますが、後者はすべての仕様で' jasmine.createSpyObj(...) 'を更新することができます。これは望ましい動作です。 – estus

関連する問題