Единичное тестирование Угловые заводы, имеющие зависимости
При тестировании устройства Angular factory (с помощью Karma + Jasmine), как я вставляю зависимость stub в тестируемый factory?
Здесь мой factory:
mod = angular.module('myFactoryMod', []);
mod.factory('myFactory', [
'$log', 'oneOfMyOtherServices', function($log, svc) {
return makeSomethingThatDoesSomethingWithTheseDependencies($log, svc);
}
]);
oneOfMyOtherServices
требуется при создании экземпляра factory.
Здесь мой тест:
it('can get an instance of my factory', function() {
var oneOfMyOtherServicesStub;
angular.mock.module('myFactoryMod');
oneOfMyOtherServicesStub = {
someVariable: 1
};
//****How do I get my stub in my target? ****
angular.mock.inject(['myFactory', function(target) {
expect(target).toBeDefined();
}
]);
})
N.B. Я знаю, что $controller
позволяет это для контроллеров, но я не вижу эквивалента для заводов.
Ответы
Ответ 1
Есть два способа сделать что-то вроде этого, о котором я знаю:
- Используйте
$provide
и анонимный модуль для ввода макета.
- Ввести услугу, которую вы хотели бы высмеять, и использовать функцию шпионажа жасмина для предоставления макетных значений.
Вторая опция работает только в том случае, если вы точно знаете, какие методы тестируют ваш код в инжектируемой службе, и вы можете легко их издеваться. Поскольку вы, кажется, получаете доступ к свойству данных в службе (а не к методу), лучший вариант для первого варианта.
Использование $provide
будет примерно выглядеть так:
describe('myFactory', function () {
// Load your module.
beforeEach(module('myFactoryMod'));
// Setup the mock service in an anonymous module.
beforeEach(module(function ($provide) {
$provide.value('oneOfMyOtherServicesStub', {
someVariable: 1
});
}));
it('can get an instance of my factory', inject(function(myFactory) {
expect(myFactory).toBeDefined();
}));
});
Ответ 2
Комментарий @bentsai на самом деле очень полезен для тестирования сервисов; для полноты я добавляю пример.
Вот тест для jasmine
, который делает примерно то, что вы ищете. Примечание: для этого требуется включить angular-mocks
(это то, что предоставляет такие функции, как module
и inject
).
describe('app: myApp', function() {
beforeEach(module('myApp'));
var $controller;
beforeEach(inject(function(_$controller_) {
$controller = _$controller_;
}));
// Factory of interest is called MyFactory
describe('factory: MyFactory', function() {
var factory = null;
beforeEach(inject(function(MyFactory) {
factory = MyFactory;
}))
it('Should define methods', function() {
expect(factory.beAwesome).toBeDefined()
expect(factory.beAwesome).toEqual(jasmine.any(Function))
});
});
});
Это заглушка для определения модуля и связанного с ним определения factory:
var app = angular.module('myApp', []);
app.factory('MyFactory', function() {
var factory = {};
factory.beAwesome = function() {
return 'Awesome!';
}
return factory;
});
В этом случае ясно, что использование inject()
позволяет вытягивать зависимости, как и ожидалось в вашем обычном приложении angular, и, таким образом, вы можете создавать требования для поддержки тестирования вещей, которые полагаются на них.