Модульное тестирование двух зависимых сервисов и контроллера в AngularJS

0

У меня есть демо-приложение, в котором у меня есть контроллер, который имеет заводскую зависимость, а сама фабрика зависит от другой службы. Мой код выглядит следующим образом:

var app = angular.module('sampleApp', ['ui.router']);

app.service("someServ", function(){
this.sendMsg = function(name){
    return "Hello " + name;
}
})

app.factory("appFactory", function ($http, someServ) {
function getData(url) {
    return $http.get(url);
} 

function foo(){
    var text = someServ.sendMsg("Monotype");
    alert(text);
}
return {
    getData : getData,
    foo : foo
}
})


var productsController = function ($scope, $http, appFactory) {
var pct = this;
pct.url = "http://mysafeinfo.com/api/data?list=englishmonarchs&format=json";
var jsonDataPromise = appFactory.getData(pct.url);
jsonDataPromise
    .then(function (response) {
        pct.jsonData = response.data;
    }, function (err) {
        console.log("Error is: " + error);
    });
pct.profun = function(){
    appFactory.foo();
}
};
app.controller("productsController", productsController);

productsController.$inject = ['$scope', '$http', 'appFactory'];

Я должен проверить с кармой, используя Jasmine 2.4 в качестве рамки тестирования. Я пробовал много онлайновых обучающих программ, но совершенно запутался, поскольку каждый пытается сделать что-то другое. Некоторые используют $ make для издевки службы, некоторые просто вводят фактический сервис/фабрику и используют ссылку, некоторые не дают никакого примера передачи аргументов сервисам.

Может кто-нибудь, пожалуйста, скажите мне, как сделать модульное тестирование в простых выражениях. Я уже пробовал сделать что-то вроде этого:

describe('unit testing of service and controller', function(){
beforeEach(module('sampleApp'));
var prodCtrl, $prodScope, mockfactory, mockservice;

beforeEach(function(){
    mockservice = {
        sendMsg : function(name){
            return name;
        }
    }

module(function($provide){
    $provide.value("someServ", mockservice);
});

inject(function($rootScope, $controller, $http, $q, appFactory){

    appFactory = appFactory;
    spyOn(appFactory, 'getData');
    spyOn(appFactory, 'foo');
    $prodScope = $rootScope.$new();
    prodCtrl = $controller('productsController', {
           $scope: $prodScope, $http: $http, appFactory:appFactory
        }); 
    });
});

it('appFactory has method getData and foo', function(){
    appFactory.getData();
    appFactory.foo();
    expect(appFactory.getData).toHaveBeenCalled();
    expect(appFactory.foo).toHaveBeenCalled();
})
it('productsController gets a promise back from getData', function(){
    var url = "sample url";
    var myPromise = prodCtrl.getData(url);
    myPromise.then(function(){console.log("Promise returned");})
})
it('foo calls service method sendMsg', function(){
    prodCtrl.profun();
    expect(mockservice.sendMsg).toHaveBeenCalled();
})
});
  • 0
    Этот вопрос слишком широк. В идеальном случае модульные тесты не тестируют какую-либо функциональность за пределами сервиса, и поэтому вы должны тестировать каждый сервис / фабрику отдельно и проверять любые зависимости. Используйте шпионов Жасмин для возврата определенных ответов при вызове определенного метода. Используйте ng-mock $ httpBackend для проверки HTTP-ответов.
Теги:
unit-testing
karma-jasmine
karma-runner

1 ответ

0
Лучший ответ

Я, наконец, смог решить эту проблему. Мой код выглядит так:

var app = angular.module('sampleApp', []);

app.service("someServ", function(){
this.sendMsg = function(name){
    return "Hello " + name;
}
})

app.factory("appFactory", function ($q, someServ) {
function getData() {
    var defer = $q.defer();
    defer.resolve("Success message");
    return defer.promise;
} 

function foo(){
    var text = someServ.sendMsg("Monotype");
    alert(text);
}
return {
    getData : getData,
    foo : foo
    }
})


app.controller("mainController", ['$scope', '$http','appFactory',     function($scope, $http, appFactory){
var mct = this;
mct.printData = function(){
    var myPromise = appFactory.getData();
    myPromise
        .then(function(data){
            alert("Promise returned successfully. Data : " + data);
        }, function(error){
            alert("Something went wrong.... Error: "  + error);
        })
}
mct.showMsg = function(){
    appFactory.foo();
}
}]);

Пример теста выглядел так:

describe('unit testing', function(){
var jsonData = {
    name: "Aosis",
    id: 12345
}   

beforeEach(module('sampleApp'));

beforeEach(module(function($provide){
    $provide.service("someServ", function(){
        //this.sendMsg = function(param){}
        this.sendMsg = jasmine.createSpy('sendMsg').and.callFake(function(param){})
    });

    $provide.factory("appFactory", function(someServ, $q){
        function getData(){
            var defer = $q.defer();
            defer.resolve("Success message");
            return defer.promise;
        }
        function foo(){
            var facParam = "some text";
            someServ.sendMsg(facParam);
        }
        return {
            getData : getData,
            foo : foo
        }
    });
}));

var $scope, mainController, appFactoryMock, someServMock;

beforeEach(inject(function($rootScope, $controller, $http, $q, appFactory, someServ){
    appFactoryMock = appFactory;
    someServMock = someServ;
    $scope = $rootScope.$new();
    mainController = $controller("mainController", {
        $scope : $scope,
        $http : $http,
        appFactory : appFactoryMock
    });

}));

//Тесты идут здесь...});

Здесь я издевался над сервисным методом как шпионом жасмина и and.callFake(function(){.....}) функцию, которая должна выполняться с использованием and.callFake(function(){.....}). Поддельная фабрика была создана, и ее методы были проверены. Я попытался создать поддельную фабрику, подобную сервису с использованием jasmine.createSpy, но return { getData: getData, foo: foo } выдавал ошибку. Следовательно, я сделал это.

Кто угодно, если есть лучшее решение или какое-то другое объяснение, пожалуйста, поделитесь.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню