8

Czy ktoś ma pomysł, jak kpić z $ httpBackend w kątowych testach e2e? Pomysł polega na żądaniu XHR podczas testów na Travis-Ci. Używam karmy do pośredniczenia w aktywach i częściach z mojej aplikacji railsowej uruchomionej na Travis. Chcę przeprowadzić testy akceptacyjne bez prawdziwych zapytań DB.

Oto część mojego pliku konfiguracyjnym karmy:

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

Oto część mojego pliku spec:

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

Próbowałem otrzymać $ httpBackend serwis poprzez $ wtryskiwacza:

$injector.get('$httpBackend') 

Ale to nie jest ten, który jest używany wewnątrz elementu iframe, w którym działają moje testy.

Kolejna próba zrobiłem używał angular.scenario.dsl, tutaj jest kod samle: przykład

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

Zastosowanie:

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

To prowadzi do następującego błędu:

<$httpBackend listing> has no method 'expectGET' 

W tej chwili nie mam pojęcia o następnym kroku. Czy ktoś próbował zrobić coś takiego, czy ten rodzaj stubowania jest naprawdę możliwy?

+0

Jak skonfigurować karmę, aby miała funkcję "wstrzykiwania" w swojej specyfikacji? Wciąż otrzymywałem ReferenceError dla moich testów – wakandan

Odpowiedz

0

To bardziej przypomina testowanie jednostek/spec. Ogólnie rzecz biorąc, powinieneś używać mocków w testach unit/spec, a nie e2e/integracji. Zasadniczo, pomyśl o testach e2e jako potwierdzających oczekiwania na najczęściej zintegrowanej aplikacji ... kpiąc z rzeczy, które pokonują cel testów e2e. Właściwie to nie jestem pewien, w jaki sposób karam wstawiłby angular-mocks.js do uruchomionej aplikacji.

Spec badanie mogłoby wyglądać ...

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

Kod nie jest związany z pytaniem - pytanie nie dotyczy testów jednostkowych, a kod dotyczy testów jednostkowych Jasmine. "inject" nie jest zdefiniowany w testach e2e. –

7

Jeśli jesteś naprawdę próbuje szydzić z backendu w teście E2E (testy te nazywane są scenariusze, natomiast specyfikacje są używane do testów jednostkowych) to właśnie zrobiłem w projekcie, nad którym pracowałem wcześniej.

Aplikacja, którą testowałem, została nazwana studentsApp. Była to aplikacja do wyszukiwania uczniów poprzez zapytanie o API REST. Chciałem przetestować aplikację bez faktycznego wysyłania zapytania do tego api.

Stworzyłem aplikację E2E o nazwie studentsAppDev, do której wstawiam studentsApp i ngMockE2E. Tam określam, jakie połączenia powinien oczekiwać program mockBackend i jakie dane należy zwrócić. Poniżej znajduje się przykład z mojego pliku 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([...]); 
}); 

Wtedy, mam pierwszy krok w moim serwerze Jenkins CI, aby zastąpić studentsApp z studentsAppDev i dodać odwołanie do angular-mocks.js w głównym pliku index.html.

+3

Nie trzeba konfigurować i tworzyć osobnej aplikacji tylko dla kpiny z $ httpBackend. Opisałem, jak to skonfigurować, aby można było używać go zarówno do testów jednostkowych, jak i E2E: http://blogs.burnsidedigital.com/2013/09/and-httpbackend-mock-for-all-unit-e2e- testy /. – Dida

+0

Ach, to dobre rozwiązanie, Dida, dzięki za to. Jest to zdecydowanie coś, na co zajrzę, gdy następnym razem będę musiał wyśmiać backend. –

+0

@Dida Link powyżej nie działa teraz.Czy możesz podać krótkie wyjaśnienie tego, co zrobiłeś? Może jako nowa odpowiedź. Dzięki. – Ena

1

Wyśmiewanie backendu jest ważnym krokiem w budowaniu złożonej aplikacji Angular.Pozwala to na testowanie bez dostępu do backendu, nie testujesz rzeczy dwa razy i nie musisz się martwić o mniejszą liczbę zależności.

Angular Multimocks to prosty sposób sprawdzenia, jak zachowuje się Twoja aplikacja z różnymi odpowiedziami z interfejsu API.

Umożliwia definiowanie zestawów fałszywych odpowiedzi API dla różnych scenariuszy jako plików JSON.

Umożliwia również łatwą zmianę scenariuszy. Czyni to, pozwalając na komponowanie "scenariuszy" z różnych próbnych plików.

Jak dodać go do swojej aplikacji

Po dodaniu wymaganych plików na swojej stronie, wystarczy dodać scenario jako zależność do aplikacji:

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

Po dodaniu tego do swojej aplikacji ty może zacząć tworzyć makiety dla wywołań API.

Powiedzmy aplikacja sprawia następujące wywołanie API:

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

Można utworzyć default mock plik:

przykładem someGames.json

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

Podczas ładowania aplikacji, połączeń to /games zwróci 200 i {"games": [{"name": "Legend of Zelda"}]}

Teraz powiedzmy, że chcesz zwrócić inną odpowiedź dla tego samego wywołania interfejsu API, możesz umieścić aplikację w innym scenariuszu, zmieniając adres URL, np. ?scenario=no-games

Scenariusz no-games można użyć innego pliku makiety, powiedzmy jednego takiego:

Przykład noGames.json

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

Teraz podczas ładowania aplikacji, wzywa do /games powróci 200 i {"games": []}

Scenariusze składają się z różnych makiet JSON w manifeście podobnym do tego:

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

Następnie można wykluczyć fałszywe pliki i usunąć zależność scenario w aplikacji produkcyjnej.