Тестирование службы angular, которая использует другую службу, использующую $http

У меня есть два угловых сервиса, которые я написал.

Один называется «searchAPI», который, по сути, принимает пользовательский ввод, формирует эластичные поисковые запросы, а затем запускает их с помощью вызова $http.get.

//searchAPI

service = {
    executeSearch: function(input, resultsPerPage, pageNumber){
        request = // some well tested logic that I know works to create a query string
        return $http.get(request);
    }
}

И еще один под названием typeAhead, который использует мой searchAPI для получения списка результатов typeAhead.

//typeAhead

service = {

    typeAheadContent: [],

    buildTypeAheadContent: function(input){
        return searchAPI.executeSearch(input, 10, 1).then(function(res){
            for(var i = 0; i < res.length; i++){
                service.typeAheadContent.push(res[i]);
            }
        });
    },  

    getTypeAheadResults: function(input){
        return service.buildTypeAheadContent(input).then(function(){
            return service.typeAheadContent;
        });     
    }
};

Несколько вещей здесь.

1) Я все еще осваиваю angular, поэтому я не знаю, полностью ли мои настройки обещания соответствуют номиналу или нет. У меня есть и другие способы использования функциональности построения запросов searchAPI, помимо моего typeahead, поэтому я хотел сделать сборщик/исполнитель запросов отдельной вещью.

2) Мне нужна помощь в тестировании этого сервиса typeAhead. Для модульных тестов, как я могу гарантировать, что searchAPI на самом деле не переходит к моему бэкэнду, а вместо этого возвращает какие-то фиктивные данные или фиктивное обещание или что-то в этом роде? Что-то вроде этого было бы идеально, если бы я мог это сделать.

searchAPI.executeSearch = function(){
    return [
        'item1',
        'item2',
        'item3'
    ]
}

Я пытался сделать что-то подобное в своих тестах жасмина, но, издеваясь над ним таким образом, я не вызываю обещание, а просто устанавливаю возвращаемое значение.

Может ли кто-нибудь помочь мне начать работу с моей настройкой и издеваться над некоторыми обещаниями?

////РЕДАКТИРОВАТЬ////

Вот моя перед каждой функцией в моем тесте на жасмин.

var searchAPI, typeAhead;
beforeEach(inject($rootScope, $injector, $q)
{
    typeAhead = $injector.get('typeAhead');
    searchAPI = $injector.get('searchAPI');
    searchAPI.executeSearch = function(input, resultsPerPage, pageNumber){

        // this is being alerted just fine
        alert("Inside mock");
        return $q.when([
            'item1', 'item2', 'item3'
        ]);
    }
    $rootScope.$digest();
}));

it('should construct typeahead stuff', function(){

    searchAPI.executeSearch("hello", 10, 1).then(function(res){

        //this is not being alerted
        alert(res);
    });
    typeAhead.buildTypeAheadContent("test");
});

Поэтому я включил несколько вещей, которые помогут в отладке. Строка кода, которая предупреждает «Inside Mock», действительно предупреждается, поэтому я знаю, что моя фиктивная вещь, которую я назначил для executeSearch, настроена правильно. Однако код внутри блока .then не предупреждается, поэтому мое обещание не должно быть разрешено или что-то в этом роде...


person Zack    schedule 02.12.2014    source источник


Ответы (1)


Ваше использование обещаний звучит просто прекрасно и соответствует тому, как оно должно выглядеть. Это хорошо.

Что касается вашей проблемы - я бы, вероятно, издевался над ней, чтобы отразить исходный API - издеваться над обещаниями со статическим значением - вы можете использовать $q.when:

searchAPI.executeSearch = function(){
    return $q.when([
        'item1',
        'item2',
        'item3'
    ]);
};

$q.when преобразует внешнее (не Angular) обещание или простое значение в обещание Angular — в данном случае ваш массив.

person Benjamin Gruenbaum    schedule 02.12.2014
comment
Спасибо за ответ. Я попробую это после обеда и посмотрю, делает ли это то, что мне нужно, тогда вы получите ваше согласие :) - person Zack; 02.12.2014
comment
К сожалению, это все еще не совсем то, что я хочу. В моем тесте я попробовал searchAPI.executeSearch().then(function(res){alert(res);}); и ничего не предупредили. - person Zack; 03.12.2014
comment
Попробуйте добавить $rootScope.digest() после него, если вы не используете 1.3 - person Benjamin Gruenbaum; 03.12.2014
comment
Я не знаю, так это или нет, но я попытался добавить $rootScope.digest() после настройки searchAPI.executeSearch() и получил сообщение об ошибке $rootScope.digest не является функцией - person Zack; 03.12.2014
comment
ok $rootScope.$digest исправил ^ эту проблему, но я по-прежнему не вижу никаких предупреждений, когда пытаюсь выполнить searchAPI.executeSearch().then(function(res){alert(res);}); - person Zack; 03.12.2014
comment
Да, это $digest - также вам нужно получить ссылку на корневую область Angular. - person Benjamin Gruenbaum; 03.12.2014
comment
Я передаю его через мой beforeEach в тесте, я отредактирую свой исходный пост, чтобы показать пример. - person Zack; 03.12.2014
comment
Хорошо, он опубликован, код, который я добавил, был слишком длинным, чтобы действительно показать то, что я хотел показать. Если вы посмотрите, вы увидите, что я передаю $rootScope через beforeEach. - person Zack; 03.12.2014