Как проверить работоспособность углового декоратора
У меня есть декоратор в Angular, который собирается расширить функциональность сервиса $ log, и я хотел бы протестировать его, но я не вижу способа сделать это. Вот заглушка моего декоратора:
angular.module('myApp')
.config(function ($provide) {
$provide.decorator('$log', ['$delegate', function($delegate) {
var _debug = $delegate.debug;
$delegate.debug = function() {
var args = [].slice.call(arguments);
// Do some custom stuff
window.console.info('inside delegated method!');
_debug.apply(null, args);
};
return $delegate
}]);
});
Обратите внимание, что это в основном отменяет $log.debug()
метод, затем вызывает его после выполнения некоторых пользовательских вещей. В моем приложении это работает, и я вижу 'inside delegated method!'
сообщение в консоли. Но в моем тесте я не получаю этот вывод.
Как я могу проверить функциональность моего декоратора?
В частности, как я могу ввести мой декоратор так, чтобы он на самом деле украшает мой $log
макет реализации (см. ниже)?
Вот мой текущий тест (мокко / чай, но это не очень актуально):
describe('Log Decorator', function () {
var MockNativeLog;
beforeEach(function() {
MockNativeLog = {
debug: chai.spy(function() { window.console.log("\nmock debug call\n"); })
};
});
beforeEach(angular.mock.module('myApp'));
beforeEach(function() {
angular.mock.module(function ($provide) {
$provide.value('$log', MockNativeLog);
});
});
describe('The logger', function() {
it('should go through the delegate', inject(function($log) {
// this calls my mock (above), but NOT the $log decorator
// how do I get the decorator to delegate the $log module??
$log.debug();
MockNativeLog.debug.should.have.been.called(1);
}));
});
});
1 ответ
Исходя из прикрепленного пакета ( http://j.mp/1p8AcLT), исходная версия - это (в основном) нетронутый код, предоставленный @jakerella (незначительные корректировки синтаксиса). Я пытался использовать те же зависимости, которые я мог извлечь из оригинального поста. Заметка tests.js:12-14
:
angular.mock.module(function ($provide) {
$provide.value('$log', MockNativeLog);
});
Это полностью отменяет родной $log
Сервис, как и следовало ожидать, с MockNativeLog
реализация обеспечивается в начале испытаний, потому что angular.mock.module(fn)
действует как функция конфигурации для модуля макета. Поскольку функции конфигурации выполняются в порядке FIFO, эта функция забивает декорированные $log
Обслуживание.
Одним из решений является повторное применение декоратора внутри этой функции конфигурации, как вы можете видеть из версии 2 plunk (постоянная ссылка была бы хорошей, Plunker), tests.js:12-18
:
angular.mock.module('myApp', function ($injector, $provide) {
// This replaces the native $log service with MockNativeLog...
$provide.value('$log', MockNativeLog);
// This decorates MockNativeLog, which _replaces_ MockNativeLog.debug...
$provide.decorator('$log', logDecorator);
});
Однако этого недостаточно. Декоратор @jakerella определяет заменяет debug
метод $log
сервис, вызывая последующий вызов MockNativeLog.debug.should.be.called(1)
терпеть неудачу. Метод MockNativeLog.debug
больше не является шпионом chai.spy
так что спички не будут работать.
Вместо этого обратите внимание, что я создал дополнительного шпиона в tests.js:2-8
:
var MockNativeLog, MockDebug;
beforeEach(function () {
MockNativeLog = {
debug: MockDebug = chai.spy(function () {
window.console.log("\nmock debug call\n");
})
};
});
Этот код может быть проще для чтения:
MockDebug = chai.spy(function () {
window.console.log("\nmock debug call\n");
});
MockNativeLog = {
debug: MockDebug
};
И это все еще не является хорошим результатом тестирования, просто проверка работоспособности. Это облегчение после того, как в течение нескольких часов ударился головой о вопрос "почему бы не работать".
Обратите внимание, что я дополнительно реорганизовал функцию декоратора в глобальную область видимости, чтобы я мог использовать ее в tests.js
без необходимости переопределять его. Лучше было бы преобразовать в надлежащую службу с $provider.value()
Но это задание было оставлено ученику в качестве упражнения... Или кому-то менее ленивому, чем я.:D