8

有沒有人有一個想法如何嘲笑角e2e測試$ httpBackend? 這個想法是在travis-ci上運行測試時對XHR請求進行存根操作。 我正在使用karma代理Travis上運行的rails應用程序中的資產和部分。 我想做沒有真正的數據庫查詢驗收測試。

這裏是我的人緣配置文件的一部分:

... 
files = [ 
    MOCHA, 
    MOCHA_ADAPTER, 

    'spec/javascripts/support/angular-scenario.js', 
    ANGULAR_SCENARIO_ADAPTER, 

    'spec/javascripts/support/angular-mocks.js', 
    'spec/javascripts/e2e/**/*_spec.*' 
]; 
... 

proxies = { 
    '/app': 'http://localhost:3000/', 
    '/assets': 'http://localhost:3000/assets/' 
}; 
... 

這裏是我的規格文件的一部分:

beforeEach(inject(function($injector){ 
    browser().navigateTo('/app'); 
})); 

it('should do smth', inject(function($rootScope, $injector){ 
    input('<model name>').enter('smth'); 
    //this is the point where I want to stub real http query 
    pause(); 
})); 

我試圖獲得$ httpBackend到$注射器服務:

$injector.get('$httpBackend') 

但是這不是在我的測試運行的iframe內部使用的。

下一個嘗試,我用angular.scenario.dsl做,這裏是代碼samle:

angular.scenario.dsl('mockHttpGet', function(){ 
    return function(path, fakeResponse){ 
    return this.addFutureAction("Mocking response", function($window, $document, done) { 
     // I have access to window and document instances 
     // from iframe where my tests run here 
     var $httpBackend = $document.injector().get(['$httpBackend']); 
     $httpBackend.expectGET(path).respond(fakeResponse) 
     done(null); 
    }); 
    }; 
}); 

用例:

it('should do smth', inject(function($rootScope, $injector){ 
    mockHttpGet('<path>', { /* fake data */ }); 
    input('search.name').enter('mow'); 
    pause(); 
})); 

這將導致以下錯誤:

<$httpBackend listing> has no method 'expectGET' 

所以,在這一點上,我不知道下一步。有沒有人嘗試過這樣的事情,這種類型的茬真的有可能嗎?

+0

你如何配置你的業力在你的規範中有「注入」功能?我一直在爲我的測試收到ReferenceError – wakandan

回答

0

這種感覺更像是單元/規範測試。一般而言,您應該在單元/規範測試中使用模擬而不是e2e /集成測試。基本上,將e2e測試看作是一個主要集成應用程序的期望...嘲笑某些事情會挫敗e2e測試的目的。事實上,我不確定karam如何將angular-mocks.js插入正在運行的應用程序。

該規範的測試可能看起來像......

describe('Controller: MainCtrl', function() { 
    'use strict'; 

    beforeEach(module('App.main-ctrl')); 

    var MainCtrl, 
     scope, 
     $httpBackend; 

    beforeEach(inject(function ($controller, $rootScope, $injector) { 
     $httpBackend = $injector.get('$httpBackend'); 
     $httpBackend.when('GET', '/search/mow').respond([ 
      {} 
     ]); 
     scope = $rootScope.$new(); 
     MainCtrl = $controller('MainCtrl', { 
      $scope: scope 
     }); 
    })); 

    afterEach(function() { 
     $httpBackend.verifyNoOutstandingExpectation(); 
     $httpBackend.verifyNoOutstandingRequest(); 
    }); 

    it('should search for mow', function() { 
     scope.search = 'mow'; 
     $httpBackend.flush(); 
     expect(scope.accounts.length).toBe(1); 
    }); 
}); 
+0

代碼與問題無關 - 問題不在於單元測試,代碼是針對Jasmine單元測試的。 e2e測試中未定義'inject'。 –

7

如果你真的想要模擬出在E2E測試後端(此類測試稱爲場景,而規範是用於單元測試)那麼這就是我在前一個項目中所做的工作。

我正在測試的應用程序被稱爲studentsApp。這是一個通過查詢REST API來搜索學生的應用程序。我想測試應用程序而不用實際查詢api。

我創建了一個名爲studentsAppDev的E2E應用程序,我將studentsAppngMockE2E注入。在那裏我定義了什麼叫mockBackend應該期望什麼和返回什麼數據。以下是我studentsAppDev文件的例子:

"use strict"; 

// This application is to mock out the backend. 
var studentsAppDev = angular.module('studentsAppDev', ['studentsApp', 'ngMockE2E']); 
studentsAppDev.run(function ($httpBackend) { 

    // Allow all calls not to the API to pass through normally 
    $httpBackend.whenGET('students/index.html').passThrough(); 

    var baseApiUrl = 'http://localhost:19357/api/v1/'; 
    var axelStudent = { 
     Education: [{...}], 
     Person: {...} 
    }; 
    var femaleStudent = { 
     Education: [{...}], 
     Person: {...} 
    }; 
    $httpBackend.whenGET(baseApiUrl + 'students/?searchString=axe&') 
     .respond([axelStudent, femaleStudent]); 
    $httpBackend.whenGET(baseApiUrl + 'students/?searchString=axel&')  
     .respond([axelStudent, femaleStudent]); 
    $httpBackend.whenGET(baseApiUrl + 'students/?searchString=axe&department=1&') 
     .respond([axelStudent]); 
    $httpBackend.whenGET(baseApiUrl + 'students/?searchString=axe&department=2&') 
     .respond([femaleStudent]); 
    $httpBackend.whenGET(baseApiUrl + 'students/?searchString=axe&department=3&')  
     .respond([]); 

    ... 

    $httpBackend.whenGET(baseApiUrl + 'departments/?teachingOnly=true') 
     .respond([...]); 
    $httpBackend.whenGET(baseApiUrl + 'majors?organization=RU').respond([...]); 
}); 

然後,我在我的詹金斯CI服務器的第一步,以取代studentsAppstudentsAppDev,並在主index.html文件添加引用angular-mocks.js

+3

不需要設置和創建一個單獨的應用程序來模擬$ httpBackend。我介紹瞭如何進行設置,以便它可以用於單元和E2E測試:http://blogs.burnsidedigital.com/2013/09/and-httpbackend-mock-for-all-unit-e2e- testings /。 – Dida

+0

哦,這是一個很好的解決方案迪達,謝謝你的寫作。這絕對是我下次不得不嘲笑後端的時候要考慮的事情。 –

+0

@Dida上面的鏈接現在不工作。你能提供你做了什麼的簡短解釋嗎?也許作爲一個新的答案。謝謝。 – Ena

1

嘲笑你的後端是構建一個複雜的Angular應用程序的重要一步。它允許在無需訪問後端的情況下完成測試,您不需要測試兩次,也不需要擔心依賴關係。

Angular Multimocks是一個簡單的方法來測試您的應用程序從一個API不同的反應行爲。

它允許您爲不同場景定義一組模擬API響應作爲JSON文件。

它還允許您輕鬆更改場景。它通過允許 從不同的模擬文件中構建「場景」來實現。

如何將其添加到您的應用程序

添加必需的文件到您的網頁後,簡單地作爲一個依賴添加scenario到應用程序:

angular 
    .module('yourAppNameHere', ['scenario']) 
    // Your existing code here... 

一旦這個添加到你的應用程序你可以開始爲API調用創建模擬。

比方說你的應用程序,使得下面的API調用:

$http.get('/games').then(function (response) { 
    $scope.games = response.data.games; 
}); 

您可以創建一個default模擬文件:

someGames.json

{ 
    "httpMethod": "GET", 
    "statusCode": 200, 
    "uri": "/games", 
    "response": { 
    "games": [{"name": "Legend of Zelda"}] 
    } 
} 

當你加載你的應用程序,調用到/games將返回200{"games": [{"name": "Legend of Zelda"}]}

現在讓我們說你想爲同一個API調用返回一個不同的響應,你可以通過改變URL來將應用置於不同的場景中。 ?scenario=no-games

no-games場景可以使用不同的模擬文件,可以說一個是這樣的:

noGames.json

{ 
    "httpMethod": "GET", 
    "statusCode": 200, 
    "uri": "/games", 
    "response": { 
    "games": [] 
    } 
} 

現在

當加載應用程序,調用/games將返回200{"games": []}

方案由各種JSON的嘲笑在這樣一個清單:

{ 
    "_default": [ 
    "games/someGames.json" 
    ], 
    "no-games": [ 
    "games/noGames.json" 
    ] 
} 

然後,您可以排除模擬文件並去除生產應用程序中的scenario依賴項。