2016-03-21 15 views
1

私は、インターネット上にこの質問に関する情報がたくさんあることを知っています(私を信じて、全部で2日を費やしました)。これまで私が見つけたものは、私を本当に助けてくれません。ここでその角度依存性を嘲笑せずに角度コントローラをテストする

は、私がテストしたいコントローラである:ここでは

(function() { 
    "use strict"; 

    angular 
     .module("productManagement") 
     .controller("ProductListController", ["productResource", ProductListController]); 

    function ProductListController(productResource) { 
     var vm = this; 

     productResource.query(function(data) { 
      vm.products = data; 
     }); 

     vm.showImage = false; 

     vm.toggleImage = function() { 
      vm.showImage = !vm.showImage; 
     } 
    } 
})(); 

作品ジャスミンのテストです:

describe('Controller: ProductListController', function() { 

    var ProductListController; 

    beforeEach(function() { 
     module('productManagement');  

     inject(function($controller) { 
      ProductListController = $controller('ProductListController', {}); 
     }); 
    }); 

    it ('showImage should be false', function() { 
     expect(ProductListController.showImage).toBe(false); 
    }); 
}); 

をすべて良いが、今私が作るためにvm.productsをテストしたいですそのデータがあることを確認してください。

ただし、以下のジャスミンテストが失敗した(これは私が実際にテストしたいものです):

describe('Controller: ProductListController', function() { 

    var ProductListController; 

    beforeEach(function() { 
     module('productManagement');  

     inject(function($controller) { 
      ProductListController = $controller('ProductListController', {}); 
     }); 
    }); 

    it ('products should be defined', function() { 
     expect(ProductListController.products).toBeDefined(); 
    }); 
}); 

エラーは「未定義が定義されることを想定して」されています。だから何らかの理由で製品にデータが取り込まれていないのですが、角度付きアプリを正常に動かすとうまくいきます。

これで、のproductResourceの内部で何が起こっているのだろうかと疑問に思うかもしれません。 さて、ここであなたが行く:

(function() { 
    "use strict"; 

    angular 
     .module("common.services") 
     .factory("productResource", ["$resource", productResource]); 

    function productResource($resource) { 
     return $resource("/api/products/:productId"); 
    } 

})(); 

私の角度アプリは、実際にいくつかの偽の製品情報を返すために$ httpBackend使用しています。だから私はジャスミンテストでこれを嘲笑したくない、それは私のモックを嘲笑するようなものだろうから。しかし、技術的にはこれは単体テストなので、私はジャスミンテストでhttpBackendを真似しなければなりません。

describe('Controller: ProductListController', function() { 

    var ProductListController, httpBackend, $resource; 

    beforeEach(function() { 
     module('productManagement');  

     inject(function(_$httpBackend_, $controller, _$resource_) { 
      httpBackend = _$httpBackend_; 
      ProductListController = $controller('ProductListController', {}); 
      $resource = _$resource_; 
     }); 
    }); 

    /*afterEach(function() { 
     //httpBackend.flush(); 
     httpBackend.verifyNoOutstandingExpectation(); 
     httpBackend.verifyNoOutstandingRequest(); 
    });*/ 

    it ('products should be defined', function() {     

     var productsUrl = '/api/products/:productId'; 
     var products; 

     httpBackend.whenGET(productsUrl).respond({ 
      'one': 1, 
      'two': 2 
     }); 

     httpBackend.expectGET(productsUrl); 

     var rec = $resource("/api/products/:productId"); 

     rec.query(function(data) { 
      products = data; 
     }); 

     //httpBackend.flush(); 

     expect(products.one).toBe(1); 
    }); 
}); 

私はhttpBackend.flushを(コメントアウトする必要がある)エラーのため:まあ、私はあまりにも....ここ

が、私は私のテストでhttpBackendを模擬しようとしたコードであることを試してみました'待つ必要がありません!'また、「不満足なリクエスト」などの他のエラーのために、afterEach関数をコメントアウトする必要があります。

これでうまくいきましたが、コントローラの機能はテストしていませんが、$ resourceをテストしています。だから、これはちょうど私にとって正しいとは思わない。

私が間違っていることを教えてもらえますか?私は最初の方法をやってみたいと思っていますが、この時点で私は何でもできるでしょう!

答えて

1

私はこの問題を抱えている身体があれば、これを理解しました。ジャスミンテストで作成された疑似データと、サービスで送信された実際のデータの両方をテストできるようになりました。ここで

は、コードウォークスルーです:

// ProductListController.js 

(function() { 
    "use strict"; 

    angular 
     .module("productManagement") 
     .controller("ProductListController", ["productResource", ProductListController]); 

    function ProductListController(productResource) { 
     var vm = this; 

     productResource.query(function(data) { 
      vm.products = data; 
     }); 

     vm.showImage = false; 

     vm.whatever = function() { 
      return 'returning'; 
     } 

     vm.toggleImage = function() { 
      vm.showImage = !vm.showImage; 
     } 
    } 
})(); 

ここで適切にコントローラをテストするユニットであるジャスミンのコードがあり、私の中productResource.query()方法ことを確認するために:ここで

は私がテストしてい私の角度コントローラですコントローラは正しいデータを `vm.products '変数に割り当てています。私はこのデータをジャスミンで嘲笑します。

describe('Controller: ProductListController', function() { 

    var ProductListController, $httpBackend; 

    beforeEach(module('productManagement')); 

    beforeEach(inject(function($controller, _$httpBackend_) { 
     ProductListController = $controller('ProductListController', {}); 
     $httpBackend = _$httpBackend_; 
    })); 

    it ('products ', function() { 
     $httpBackend.expectGET('/api/products').respond([{'productId': 13}]); 
     $httpBackend.flush(); 
     expect(ProductListController.products[0].productId).toBe(13); 
    }); 
}); 

$httpBackend.expectGET基本的に何かを待っている - この場合は私のコントローラ - APIを呼び出すと、そのオブジェクト[{'productId': 13}]で応答しています。これは私のバックエンドを適切に模倣して、私たちがコントローラの機能について単体テストを行うことを可能にします。

実際にAPI呼び出しを行うproductResourceコードは、作成した工場の裏側にあり、自分のコントローラーで使用しています。

(function() { 
    "use strict"; 

    angular 
     .module("common.services") 
     .factory("productResource", ["$resource", productResource]); 

    function productResource($resource) { 
     return $resource('/api/products/:productId'); 
    } 

})(); 

さて、私の元の質問に答えるために:私がテストし、どのような私たちのバックエンドを見たいと思った場合、私のジャスミン試験でHTTPレスポンスをあざけるせずにをここにそこに好奇心心のためにproductResourceコードですコントローラに送信していますが、どうすればいいですか?

「本物の」バックエンドを使用していません。私は本当のバックエンドをシミュレートするために私の実際の角型アプリケーションで実際に$ httpBackendを使用しています。これは、私が角度チュートリアルに従ったためであり、それはチュートリアルのやり方です。ですから、そのファイルに1行のコードを追加する必要があります。ここにそのファイルのスニッピと追加されたコード行があります。

(function() { 
"use strict"; 

var app = angular 
      .module("productResourceMock", ["ngMockE2E"]); 

app.run(function ($httpBackend) { 
    var products = [ 
     { 
      "productId": 1, 
      "productName": "Leaf Rake", 
      "productCode": "GDN-0011", 
      "releaseDate": "March 19, 2009", 
      "description": "Leaf rake with 48-inch handle", 
      "cost": 9.00, 
      "price": 19.95, 
      "category": "garden", 
      "tags": ["leaf", "tool"], 
      "imageUrl": "http://openclipart.org/image/300px/svg_to_png/26215/Anonymous_Leaf_Rake.png" 
     }, 
     { 
      "productId": 5, 
      "productName": "Hammer", 
      "productCode": "TBX-0048", 
      "releaseDate": "May 21, 2013", 
      "description": "Curved claw steel hammer", 
      "cost": 1.00, 
      "price": 8.99, 
      "category": "toolbox", 
      "tags": ["tool"], 
      "imageUrl": "http://openclipart.org/image/300px/svg_to_png/73/rejon_Hammer.png" 
     }, 
     { 
      "productId": 2, 
      "productName": "Garden Cart", 
      "productCode": "GDN-0023", 
      "releaseDate": "March 18, 2010", 
      "description": "15 gallon capacity rolling garden cart", 
      "cost": 20.00, 
      "price": 32.99, 
      "category": "garden", 
      "tags": ["barrow", "cart", "wheelbarrow"], 
      "imageUrl": "https://openclipart.org/image/300px/svg_to_png/58471/garden-cart.png" 
     } 
    ]; 

    var productUrl = "/api/products"; 
    $httpBackend.whenGET(productUrl).respond(products); 

    // This is the line I added to make my jasmine test work properly 
    $httpBackend.expectGET(productUrl).respond(products); 

そして今ジャスミンテスト。上記の方法と全く同じです。

it ('products should really be defined', function() { 
    $httpBackend.flush(); 
    expect(ProductListController.products[0].productId).toBe(1); 
}); 

私のコントローラは、すでにのREST APIをpingを実行するので、私は最初、バックエンドをフラッシュ:だからここだけit方法があります。それから、私はデータをチェックして、確かに、それは私の虚偽のバックエンドが送られたものを含んでいます。

実際のバックエンドでデータの正確性をテストする場合は、ジャスミンテストがうまくいくはずです。

申し訳ありませんが、私はこのような問題を抱えています。

1

$ httpBackendは、あなたのアプリケーションは、潜在的なHTTP呼び出しにどのように反応するかを確認することができますので、あなたは、それが本当のバックエンドのimitatationの一種である(テストコードで実際にモック HTTP応答に使用することができますngMockモジュールサービスです)。一方、運用コードでは、$リソースサービスを使用しています。この場所では$ httpBackendとは関係ありません。このコード

it ('products should be defined', function() { 
    $httpBackend.expectGET('/api/products').respond({}); 
    $httpBackend.flush(); 
    expect(ProductListController.products).toBeDefined(); 
}); 

チェックアウトは、我々は、それがバックエンドから提供されたかのように、あなたのproductResourceがデータを受信するように、実際のバックエンドを模倣するために、あなたのテストに2行のコードを追加しました。

+0

実際に私の角型アプリケーションで$ httpBackendを使用しています。私は、複数のアプリケーションを構築するために、複数のチュートリアルを行ってきました。それが、アプリケーションでやっていることです。したがって、私はジャスミンテストで$ httpBackendを再び模倣する必要があるとは感じません。それは私のジャスミンテストで$ httpBackendを模倣しようとすると、私はまだ成功していないと言われています。提案されたアプローチでは、「フラッシュする要求がありません!」というエラーがスローされます。ジャスミンテストでURLを実際に呼び出すために$リソースを取得するのがうまくいかず、正しく動作していないようです。そこに任意のアイデア? – BradStell

+0

1)プロダクションコードで** $ httpBackend **を使用していることを意味しますか? 2)URLを呼び出すために$ resourceを取得しようとしていますか? $ resourceのフードの下で呼び出されるURLは、** $ httpBackend.expectGET(URL)** – piethraz

+0

で指定されているものと同じでなければなりません1)yes "production"コードで$ httpBackendを使用しています。実際の制作ではなく、チュートリアルに従っていました。チュートリアルでは、$ httpBackendを使用してチュートリアルの目的でデータベースをシミュレートするサービスを設定しています。 2)$ httpBackBack.expectGETが期待しているのと同じurlである私のジャスミンコードで$ resourceを使用しています。 – BradStell

関連する問題