Как вы издеваетесь над сервисом в AngularJS при модульном тестировании с жасмином?

Скажем, у меня есть служба shop, которая зависит от двух служб с сохранением состояния schedule и warehouse. Как я вставляю разные версии schedule и warehose в shop для модульного тестирования?

Здесь мое обслуживание:

angular.module('myModule').service('shop', function(schedule, warehouse) {
    return {
        canSellSweets : function(numRequiredSweets){
             return schedule.isShopOpen()
                 && (warehouse.numAvailableSweets() > numRequiredSweets);
        }
    }
});

Вот мои издевательства:

var mockSchedule = {
    isShopOpen : function() {return true}
}
var mockWarehouse = {
    numAvailableSweets: function(){return 10};
}

Вот мои тесты:

expect(shop.canSellSweets(5)).toBe(true);
expect(shop.canSellSweets(20)).toBe(false);

Ответ 1

beforeEach(function () {
  module(function ($provide) {
    $provide.value('schedule', mockSchedule);
  });
});

Модуль - это функция, предоставляемая модулем angular -mocks. Если вы передаете строковый аргумент, загружается модуль с соответствующим именем и все поставщики, контроллеры, службы и т.д. Доступны для спецификации. Обычно они загружаются с использованием функции впрыска. Если вы передадите функцию обратного вызова, она будет вызвана с помощью службы Angular $инжектор. Затем эта служба обращается к аргументам, переданным функции обратного вызова, и пытается определить, какие зависимости должны быть переданы в обратный вызов.

Ответ 2

Улучшение ответа Atilla и прямой ответ на комментарий KevSheedy, в контексте module('myApplicationModule') вы бы сделали следующее:

beforeEach(module('myApplicationModule', function ($provide) {
  $provide.value('schedule', mockSchedule);
}));

Ответ 3

С CoffeeScript я запускаю некоторые проблемы, поэтому я использую null в конце:

beforeEach ->
  module ($provide) ->
    $provide.value 'someService',
      mockyStuff:
        value : 'AWESOME'
    null

Ответ 4

Вы можете посмотреть здесь дополнительную информацию

https://docs.angularjs.org/guide/services#unit-testing

Вы хотите использовать службу $предоставлять. В вашем случае

$provide.value('schedule', mockSchedule);

Ответ 5

Недавно я выпустил модуль ngImprovedTesting, который должен облегчить тестирование в режиме AngularJS.

В вашем примере вам нужно будет только заменить в своем тесте Жасмин...

beforeEach(module('myModule'));

... с...

beforeEach(ModuleBuilder.forModule('myModule').serviceWithMocks('shop').build());

Для получения дополнительной информации о ngImprovedTesting проверьте его вводное сообщение в блоге: http://blog.jdriven.com/2014/07/ng-improved-testing-mock-testing-for-angularjs-made-easy/

Ответ 6

Проще всего добавить макет в модуль следующим образом:

    beforeEach(function () {
    module('myApp');
    module({
      schedule: mockSchedule,
      warehouse: mockWarehouse
     }
    });
  });

вы можете использовать инъекцию, чтобы получить ссылку на эти макеты для предпроверочных манипуляций:

var mockSchedule;
var mockWarehouse;

beforeEach(inject(function (_schedule_, _warehouse_) {
     mockSchedule = _schedule_;
     mockWarehouse = _warehouse_;
}));

Ответ 7

Надеюсь, мой ответ не настолько бесполезен, но вы можете издеваться над сервисами $provide.service

beforeEach(() => {
    angular.mock.module(
      'yourModule',
      ($provide) => {
        $provide.service('yourService', function() {
          return something;
        });
      }
    );
  });

Ответ 8

Поскольку вы используете жасмин, есть альтернативный способ издеваться над вызовами с помощью шпионов жасмина (https://jasmine.github.io/2.0/introduction.html#section-Spies).

Используя их, вы можете настроить таргетинг на вызовы функций и, если необходимо, разрешить сквозной вызов. Это позволяет избежать засорения верхней части тестового файла с помощью $provision и mock.

В начале каждого теста у меня было бы что-то вроде:

var mySchedule, myWarehouse;

beforeEach(inject(function(schedule, warehouse) {

  mySchedule = schedule;
  myWarehouse = warehouse;

  spyOn(mySchedule, 'isShopOpen').and.callFake(function() {
    return true;
  });

  spyOn(myWarehouse, 'numAvailableSweets').and.callFake(function() {
    return 10;
  });

}));

и это должно работать аналогично механизму $provision, отметив, что вам нужно предоставить локальные экземпляры инъецируемых переменных, которые будут отслеживать.