簡體   English   中英

在AngularJS中對兩個相關服務和控制器進行單元測試

[英]Unit testing two dependent services and controller in AngularJS

我有一個演示應用程序,其中有一個控制器,該控制器具有一個作為依賴項的工廠,而工廠本身依賴於另一個服務。 我的代碼如下:

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作為測試框架來進行業力測試。 我嘗試了許多在線教程,但由於每個人都嘗試做不同的事情而感到完全困惑。 有些使用$ provide模擬服務,有些簡單地注入實際的服務/工廠並使用引用,有些沒有給出將參數傳遞給服務的示例。

有人可以簡單地告訴我如何進行單元測試。 我已經嘗試過這樣做:

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();
})
});

我終於能夠解決這個問題。 我的代碼如下所示:

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(){.....})執行的and.callFake(function(){.....}) 創建了一個假工廠,並對其方法進行了監視。 我嘗試使用jasmine.createSpy創建類似於服務的偽造工廠,但return { getData : getData, foo : foo }給出了錯誤。 因此,我做到了。

任何人,如果有更好的解決方案或其他解釋,請分享。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM