Jasmine и angular mocks: имитация службы, которая обрабатывает локальное хранилище

У меня есть одна служба под названием wd$cache, которая по сути представляет собой оболочку для localStorage.setItem и get.item.

Теперь я пытаюсь протестировать контроллер, который использует этот сервис для достижения определенного результата. Основная проблема заключается в том, что у меня есть оператор IF, который срабатывает только в том случае, если у вас уже установлено локальное хранилище, что сводит меня с ума! (здесь мы делаем TDD)

ОКАЗАНИЕ УСЛУГ

(function () {

angular
    .module('hub')
    .controller('promotionNotificationCtrl', promotionNotificationCtrl);

promotionNotificationCtrl.$inject = [
    'hub$promotions',
    'hub$client',
    'wd$cache'
];

function promotionNotificationCtrl(
    hub$promotions,
    hub$client,
    wd$cache) {

    var vm = this;
    activate();

    //////////

    function activate () {

        hub$promotions.get(hub$client.brand, hub$client.subbrand).success(function (data) {

            if (!wd$cache.get('hub$notification')) {

                wd$cache.add('before', 123);
            } else {

                wd$cache.add('after', 321);
            }
        });
    }
}
})(); 

ТЕСТ

describe('The promotion notification controller', function () {

var controller,
    hub$client,
    $httpBackend,
    wd$cache,
    mockData = [{

        "foo": "bar"
    },
    {
        "faa": "boo"
    }];


beforeEach(module('hub'));
beforeEach(module('wired.core'));

beforeEach(module(function ($provide) {

    hub$client = {

        brand: 'bw',
        subbrand: 'plus'
    };

    wd$cache = {

        add: function () {

        },

        get: function () {

        }
    };

    $provide.value('hub$client', hub$client);
    $provide.value('wd$cache', wd$cache);
    spyOn(wd$cache, 'add');
}));

beforeEach(inject(function ($controller, _$httpBackend_, _hub$promotions_) {

    controller = $controller('promotionNotificationCtrl');
    $httpBackend = _$httpBackend_;
    hub$promotions = _hub$promotions_;

    // request
    $httpBackend.expectGET("/umbraco/api/promotions/get/?brand=bw&lang=en&subbrand=plus").respond(200, mockData);
    $httpBackend.flush();
}));

it('should attempt to add a cache with a "before" key if no previous "hub$notification" cache was found', function () {


    expect(wd$cache.add).toHaveBeenCalledWith('before', 123); //WORKING
})

it('should attempt to add a cache with a "after" key if a previous "hub$notification" cache was found', function () {

    localStorage.setItem('hub$notification');
    wd$cache.add('hub$notification');

    expect(wd$cache.add).toHaveBeenCalledWith('after', 123); // NOT WORKING
    // CANT GET THROUGH THE IF STATEMENT
})
});

По сути, я никогда не смогу перейти к «Тестовым случаям» после блока BeforeEach, что бы я ни делал. Я пробовал все, начиная с издевательств, чтобы использовать реальное хранилище.

Любые идеи?


person DjayCi    schedule 28.01.2016    source источник
comment
Можете ли вы опубликовать ошибку, которую вы получаете в тест-раннере Karma?   -  person Jagrut    schedule 28.01.2016
comment
Совсем забыл об этом! Ожидалось, что wd$cache.add будет вызван с «после», но фактические вызовы были «до», 123   -  person DjayCi    schedule 28.01.2016


Ответы (1)


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

var cache = {};    

beforeEach(module(function ($provide) {
    // ...
    wd$cache = {
        add: function (key, value) {
            cache[key] = value;
        },
        get: function (key) {
            return cache[key];
        }
    };

    // add initial data here or in the individual tests, e.g.


    // ...
}));

Чтобы правильно настроить кеш для конкретного теста, вы можете использовать поле cache следующим образом:

cache['hub$notification'] = 'whatever value makes sense here';

Конечно, вы также можете сделать это в beforeEach.

В настоящее время вы пытаетесь сделать это следующим образом:

wd$cache.add('hub$notification');
expect(wd$cache.add).toHaveBeenCalledWith('after', 123);

Это проблематично по двум причинам:

  • Вы не обновляете кеш, потому что шпионите за методом add без .andCallThrough(). Вы должны исправить это (добавьте .andCallThrough() после создания шпиона), иначе обновления от контроллера не будут влиять на кеш.

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

person lex82    schedule 28.01.2016
comment
Это работает, только если я установил cache['hub$notification'] = 123; в перед каждым, что сделает первый тестовый перерыв, так как есть доступный кеш! it('следует попытаться добавить кеш с ключом after, если был найден предыдущий кеш hub$notification', function () { wd$cache.hub$notification = 123; expect(wd$cache.add).toHaveBeenCalledWith(' после', 123); }) - person DjayCi; 28.01.2016
comment
Это был глупый комментарий! Но в основном, делая это, вы в конечном итоге выполняете только одно из утверждений it, поскольку единственный способ заставить это работать — поставить его перед каждым! - person DjayCi; 28.01.2016
comment
Просто переместите var cache = {} во внешнюю область. Затем вы можете изменить содержимое кеша в каждом отдельном тесте, а не только в файле beforeEach. - person lex82; 28.01.2016
comment
Это было снаружи моего кода с самого начала. Даже если я установлю новый кеш для каждого ИТ, он получит только первое значение. Не уверен, почему! - person DjayCi; 28.01.2016
comment
Я обновил свой ответ. Теперь он включает объяснение, почему ваш текущий подход не работает. - person lex82; 28.01.2016