2013-12-05 2 views
3

Я хотел бы протестировать заводской метод, который запускает $ resource. Мой тест будет издеваться над реальным бэкэндом, которого еще нет.Как насмехаться с бэкэндом для приложения angularjs?

Вот пример кода завода:

app.factory('Global', function($resource){ 
    var Jogas = $resource('/jogasok/:id', {'id': '@id'}, { 
    'ujBerlet': {'method': 'POST', 'params': {'berlet': true}} 
    }); 
    var jogasok = Jogas.query(); 
    return { 
    getJogasok: function() { 
     return jogasok; 
    } 
    }; 
}) 

Мой тест будет проверить, что запрос был сделан.

Если я инициализировать мое приложение с:

app.run(function run ($httpBackend) { 
    $httpBackend.whenGET('/jogasok').respond([ 
     {id: 1, name: 'asdfasdf'}, 
     {id: 2, name: '2wrerwert'} 
     ]); 
}) 

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

Но, когда я вынимаю код запуска выше и пишу тест, все просто не работает.

describe('Global Service: ', function() { 

    beforeEach(module('bkJoga')); 
    beforeEach(inject(function($httpBackend) { 
    $httpBackend.whenGET('/jogasok').respond([ 
     {id: 1, name: 'asdfasdf'}, 
     {id: 2, name: '2wrerwert'} 
    ]); 
    })); 

    it('getJogasok should return everyone', inject(function(Global) { 
    expect(JSON.stringify(Global.getJogasok())).toBe(JSON.stringify([ 
     {id: 1, name: 'asdfasdf'}, 
     {id: 2, name: '2wrerwert'} 
    ])); 
    })); 
}); 

не работает.

ответ

5

Вот рабочее испытание на заводе-изготовителе, как вы разместили ее. Я добавил переменную $ httpBackend для введенного httpBackend. И вызов $ httpBackend.flush(). fiddle-demo (дочитал до конца для полного описания содержания скрипки)

describe('Global Service: ', function() { 
    var Global, $httpBackend 

    // load the relevant application module, with the service to be tested 
    beforeEach(module('bkJoga')); 

    beforeEach(function() { 

     // inject the mock for the http backend 
     inject(function(_$httpBackend_) { 
      $httpBackend = _$httpBackend_; 
     }); 
     // mock the response to a particular get request 
     $httpBackend.whenGET('/jogasok').respond([ 
      {id: 1, name: 'asdfasdf'}, 
      {id: 2, name: '2wrerwert'} 
     ]); 
     // inject the service to be tested 
     inject(function(_Global_) { 
      Global = _Global_; 
     }); 
    }); 

    it('should exist', function() { 
     expect(!!Global).toBe(true); 
    }); 

    it('getJogasok should return everyone', function() { 
     $httpBackend.flush(); // <------------ need to flush $httpBackend 
     expect(JSON.stringify(Global.getJogasok())).toBe(JSON.stringify([ 
      {id: 1, name: 'asdfasdf'}, 
      {id: 2, name: '2wrerwert'} 
     ])); 
    }); 
}); 

В любом случае, я бы переписать завод немного по-другому, потому что, как это в настоящее время написано, он запрашивает базу данных только при конкретизации var jogasok = Jogas.query();. Поскольку services in angularjs are singletons, в вашем приложении у вас будут только данные, как они есть во время создания экземпляра. Поэтому последующие изменения данных не будут отражаться на вашем заводе. Вот пример завода и его модульного теста, который отражает эту идею.

завод:

app.factory('GlobalBest', function ($resource) { 
    return $resource('/jogasok/:id', { 
     'id': '@id' 
    }, { 
     'ujBerlet': { 
      'method': 'POST', 
       'params': { 
       'berlet': true 
      } 
     } 
    }); 
}); 

тест:

describe('GlobalBest Service: ', function() { 
    var srv, $httpBackend; 

    beforeEach(module('bkJoga')); 

    beforeEach(function() { 
     // inject the mock for the http backend 
     inject(function (_$httpBackend_) { 
      $httpBackend = _$httpBackend_; 
     }); 

     // inject the service to be tested 
     inject(function (_GlobalBest_) { 
      srv = _GlobalBest_; 
     }); 
    }); 

    it('should exist', function() { 
     expect(!! srv).toBe(true); 
    }); 

    it('query() should return everyone', function() { 

     // mock the response to a particular get request 
     $httpBackend.whenGET('/jogasok').respond([{ 
      id: 1, 
      name: 'asdfasdf' 
     }, { 
      id: 2, 
      name: '2wrerwert' 
     }]); 

     // send request to get everyone 
     var data = srv.query(); 

     // flush the pending request 
     $httpBackend.flush(); 
     expect(JSON.stringify(data)).toBe(JSON.stringify([{ 
      id: 1, 
      name: 'asdfasdf' 
     }, { 
      id: 2, 
      name: '2wrerwert' 
     }])); 
    }); 

    it('get({id: 1}) should return object with id=1', function() { 
     // mock the response to a particular get request 
     $httpBackend.whenGET('/jogasok/1').respond({ 
      id: 1, 
      name: 'asdfasdf' 
     }); 
     var datum = srv.get({ 
      id: 1 
     }); 
     $httpBackend.flush(); 
     expect(JSON.stringify(datum)).toBe(JSON.stringify({ 
      id: 1, 
      name: 'asdfasdf' 
     })); 
    }); 
}); 

Я написал fiddle-demo с 3-х версиях сервиса: исходный сервис 'Global', новую версию 'GlobalNew' который возвращает метод query() и, наконец, версию «GlobalBest», которая возвращает непосредственно ресурс $. Надеюсь это поможет.

+0

Я пробовал это, но он терпит неудачу с ошибкой: Ошибка: нет ожидающего запроса на флеш! Заводской код, как вы можете видеть в моем вопросе. Таким образом, Jogas.query должен запускаться при вводе Global. Тем не менее, добавление к нему обратных вызовов успеха/ошибок показывает, что он никогда не вызывается. – Akasha

+0

Я взял заводской код из вашего вопроса и успешно выполнил вышеуказанный тест. Попробуйте проверить, была ли эта служба создана в тесте: 'it ('should exist exist', function() {expect (!! Global) .toBe (true);});' – klode

+0

Кроме того, поскольку ваша глобальная служба выполняет query() при создании экземпляра, вам может потребоваться переместить $ httpBackend.whenGet() перед тем, как войти в сервис «Глобальный». Я заметил, что это так, если вы запускаете тест в jsfiddle. Я изменил код выше, чтобы отразить это изменение. – klode

2

попробуйте изменить его с .toBe на .toEqual. Жасмин ссылается на ссылочное равенство с toBe и глубокое сравнение с toEqual.

+0

ТНХ для замечания, но реальный вопрос здесь о насмешливом запросе HTTP – Akasha

1

До сих пор лучшим ответом, который я мог получить, было создание другого приложения, которое наследует мое приложение +, использует службу ngMockE2E. Таким образом, должно быть возможно высмеять эти запросы.

Примечание: к сожалению, я не мог заставить его работать еще с моей испытательной среды

0

Использование angular.mock.inject для создания высмеивал экземпляра службы, а затем вам нужно позвонить flush() из фиктивного $httpBackend, что позволяет тест на явно вровень ожидающие запросы и, таким образом, сохраняя асинхронной апи из внутреннего интерфейса, позволяя при этом тест на выполнять синхронно.

describe('Global Service: ', function() { 
    var srv; 

    beforeEach(module('bkJoga')); 

    beforeEach(function() { 
     angular.mock.inject(function ($injector) { 
      srv = $injector.get('Global'); 
     }); 
    }); 

    beforeEach(inject(function ($httpBackend) { 
     $httpBackend.flush(); 
     $httpBackend.whenGET('/jogasok').respond([{ 
      id: 1, 
      name: 'asdfasdf' 
     }, { 
      id: 2, 
      name: '2wrerwert' 
     }]); 
    })); 

    it('getJogasok should return everyone', inject(function (Global) { 
     expect(JSON.stringify(Global.getJogasok())).toBe(JSON.stringify([{ 
      id: 1, 
      name: 'asdfasdf' 
     }, { 
      id: 2, 
      name: '2wrerwert' 
     }])); 
    })); 
}); 

Demo

Смежные вопросы