导航:首页 > 编程语言 > angularjs控制器初始化

angularjs控制器初始化

发布时间:2024-05-01 11:01:43

❶ angularjs 鎴愬姛lazyload鍔犺浇浜嗘帶鍒跺櫒js 浣嗘槸鎺у埗鍣ㄦ湭瀹氫箟

鎸囦护鍜屾帶鍒跺櫒鐨勪氦浜 婊戝姩鍔犺浇 涓婇潰鐨勪唬鐮佸钩娣℃棤濂囷紝鏈変釜鎺у埗鍣ㄦ湁涓鎸囦护锛坙oader锛夛紝涓嬮潰鍙浠ョ湅鍒版垜浠閫氳繃 directive鍒涘缓浜嗚繖涓鎸囦护锛屽苟涓旀垜浠閫氳繃link鐨勬柟娉曠粰浠栬祴鍊奸紶鏍囦簨浠(mouseenter)銆 var myMole = angular.mole('MyController',[]); myMole.controller('MyCtrl',function($scope){ $scope.loadData = function(){ console.log("鍔犺浇鏁版嵁..."); } }) myMole.directive('loader',function(){ return{ restrict:'AE', link:function(scope,element,attr){ element.bind('mouseenter',function(){ scope.loadData(); }) } } }) 鎴戜滑鏉ョ湅鐪嬭繍琛岀殑缁撴灉锛宱k锛屾垜浠鎵撳嵃鍑烘潵 "鍔犺浇鏁版嵁...

❷ 濡備綍浣跨敤AngularJs鎵撻犳潈闄愮$悊绯荤粺銆愮畝鏄撳瀷銆慱AngularJS


涓銆佸紩瑷

鏈鏂囧皢浠嬬粛濡備綍鎶夾ngularJs搴旂敤鍒板疄闄呴」鐩涓銆傛湰绡囨枃绔犲皢浣跨敤AngularJS鏉ユ墦閫犱竴涓绠鏄撶殑鏉冮檺绠$悊绯荤粺銆備笅闈涓嶅氳达紝鐩存帴杩涘叆涓婚樸

浜屻佹暣浣撴灦鏋勮捐′粙缁

棣栧厛鐪嬩笅鏁翠釜椤圭洰鐨勬灦鏋勮捐″浘锛




浠庝笂鍥惧彲浠ョ湅鍑烘暣涓椤圭洰鐨勪竴涓鏁翠綋缁撴瀯锛屾帴涓嬫潵锛屾垜鏉ヨ︾粏浠嬬粛浜嗛」鐩鐨勬暣浣撴灦鏋勶細

閲囩敤Asp.net Web API鏉ュ疄鐜癛EST 鏈嶅姟銆傝繖鏍风殑瀹炵幇鏂瑰紡锛屽凡杈惧埌鍚庣鏈嶅姟鐨勫叕鐢ㄣ佸垎鍒閮ㄧ讲鍜屾洿濂藉湴鎵╁睍銆俉eb灞備緷璧栧簲鐢ㄦ湇鍔℃帴鍙o紝骞朵笖浣跨敤Castle Windsor瀹炵幇渚濊禆娉ㄥ叆銆

鏄剧ず灞(鐢ㄦ埛UI)

鏄剧ず灞傞噰鐢ㄤ簡AngularJS鏉ュ疄鐜扮殑SPA椤甸潰銆傛墍鏈夌殑椤甸潰鏁版嵁閮芥槸寮傛ュ姞杞藉拰灞閮ㄥ埛鏂帮紝杩欐牱鐨勫疄鐜板皢浼氭湁鏇村ソ鐨勭敤鎴蜂綋楠屻

搴旂敤灞(Application Service)

AngularJS閫氳繃Http鏈嶅姟鍘昏锋眰Web API鏉ヨ幏寰楁暟鎹锛岃學eb API鐨勫疄鐜板垯鏄璋冪敤搴旂敤灞傛潵璇锋眰鏁版嵁銆

鍩虹鏋舵瀯灞

鍩虹鏋舵瀯灞傚寘鎷浠撳偍鐨勫疄鐜板拰涓浜涘叕鐢ㄦ柟娉曠殑瀹炵幇銆

浠撳偍灞傜殑瀹炵幇閲囩敤EF Code First鐨勬柟寮忔潵瀹炵幇鐨勶紝骞朵娇鐢‥F Migration鐨勬柟寮忔潵鍒涘缓鏁版嵁搴撳拰鏇存柊鏁版嵁搴撱

LH.Common灞傚疄鐜颁簡涓浜涘叕鐢ㄧ殑鏂规硶锛屽傛棩蹇楀府鍔╃被銆佽〃杈惧紡鏍戞墿灞曠瓑绫荤殑瀹炵幇銆

棰嗗煙灞

棰嗗煙灞備富瑕佸疄鐜颁簡璇ラ」鐩鐨勬墍鏈夐嗗煙妯″瀷锛屽叾涓鍖呮嫭棰嗗煙妯″瀷鐨勫疄鐜板拰浠撳偍鎺ュ彛鐨勫畾涔夈

浠嬬粛瀹屾暣浣撶粨鏋勫栵紝鎺ヤ笅鏉ュ皢鍒嗗埆浠嬬粛璇ラ」鐩鐨勫悗绔鏈嶅姟瀹炵幇鍜學eb鍓嶇鐨勫疄鐜般

涓夈佸悗绔鏈嶅姟瀹炵幇

鍚庣鏈嶅姟涓昏侀噰鐢ˋsp.net Web API鏉ュ疄鐜板悗绔鏈嶅姟锛屽苟涓旈噰鐢–astle Windsor鏉ュ畬鎴愪緷璧栨敞鍏ャ

杩欓噷鎷挎潈闄愮$悊涓鐨勭敤鎴风$悊鏉ヤ粙缁峈est Web API鏈嶅姟鐨勫疄鐜般

鎻愪緵鐢ㄦ埛鏁版嵁鐨凴EST鏈嶅姟鐨勫疄鐜帮細

浠庝笂闈浠g爜瀹炵幇鍙浠ョ湅鍑猴紝User REST 鏈嶅姟渚濊禆涓嶪UserService鎺ュ彛锛屽苟涓斾篃娌℃湁鍍忎紶缁熺殑鏂瑰紡灏嗘墍鏈夌殑涓氬姟閫昏緫鏀惧湪Web API瀹炵幇涓锛岃屾槸灏嗗叿浣撶殑涓浜涗笟鍔″疄鐜板皝瑁呭埌瀵瑰簲鐨勫簲鐢ㄥ眰涓锛孯est API鍙璐熻矗璋冪敤瀵瑰簲鐨勫簲鐢ㄥ眰涓鐨勬湇鍔°傝繖鏍疯捐″ソ澶勬湁锛

REST 鏈嶅姟閮ㄤ緷璧栦笌搴旂敤灞傛帴鍙o紝浣垮緱鑱岃矗鍒嗙伙紝灏嗗簲鐢ㄥ眰鏈嶅姟鐨勫疄渚嬪寲浜ょ粰鍗曠嫭鐨勪緷璧栨敞鍏ュ瑰櫒鍘诲畬鎴愶紝鑰孯EST鏈嶅姟鍙璐熻矗璋冪敤瀵瑰簲搴旂敤鏈嶅姟鐨勬柟娉曟潵鑾峰彇鏁版嵁銆傞噰鐢ㄤ緷璧栨帴鍙h屼笉渚濊禆涓庡叿浣撶被鐨勫疄鐜帮紝浣垮緱绫讳笌绫讳箣闂翠綆鑰﹀悎銆俁EST鏈嶅姟鍐呬笉鍖呮嫭鍏蜂綋鐨勪笟鍔¢昏緫瀹炵幇銆傝繖鏍风殑璁捐″彲浠ヤ娇寰楁湇鍔℃洿濂藉湴鍒嗙伙紝濡傛灉浣犲悗鏈熸兂鐢╓CF鏉ュ疄鐜癛EST鏈嶅姟鐨勶紝杩欐牱灏变笉闇瑕侀噸澶嶅湪WCF鐨凴EST鏈嶅姟绫讳腑閲嶅嶅啓涓绡嘩eb API涓鐨勯昏緫浜嗭紝杩欐椂鍊欏畬鍏ㄥ彲浠ヨ皟鐢ㄥ簲鐢ㄦ湇鍔$殑鎺ュ彛鏂规硶鏉ュ疄鐜癢CF REST鏈嶅姟銆傛墍浠ュ皢涓氬姟閫昏緫瀹炵幇鎶藉埌搴旂敤鏈嶅姟灞傚幓瀹炵幇锛岃繖鏍风殑璁捐″皢浣垮緱REST 鏈嶅姟鑱岃矗鏇村姞鍗曚竴锛孯EST鏈嶅姟瀹炵幇鏇村规槗鎵╁睍銆

鐢ㄦ埛搴旂敤鏈嶅姟鐨勫疄鐜帮細

杩欓噷搴旂敤鏈嶅姟灞傚叾瀹炶繕鍙浠ヨ繘涓姝ョ殑浼樺寲锛屽疄鐜颁唬鐮佸眰绾х殑璇诲啓鍒嗙伙紝瀹氫箟IReadOnlyService鎺ュ彛鍜孖WriteServie鎺ュ彛锛屽苟涓旀妸鍐欐搷浣滃彲浠ラ噰鐢ㄦ硾鍨嬫柟娉曠殑鏂瑰紡鎶借薄鍒癇aseService涓鍘诲疄鐜般傝繖鏍蜂竴浜涘炲垹鏀规搷浣滃疄鐜板叕鐢锛屼箣鎵浠ュ彲浠ュ皢杩欓噷鎿嶄綔瀹炵幇鍏鐢锛屾槸鍥犱负杩欎簺鎿嶄綔閮芥槸闈炲父绫讳技鐨勶紝鏃犻潪鏄鎿嶄綔鐨勫疄浣撲笉涓鏍风舰浜嗐傚叾瀹炶繖鏍风殑瀹炵幇鍦ㄦ垜鍙︿竴涓寮婧愰」鐩涓宸茬粡鐢ㄥ埌锛歄nlineStore.澶у跺彲浠ュ弬鑰冭繖涓鑷琛屽幓瀹炵幇銆


浠撳偍灞傜殑瀹炵幇锛

鐢ㄦ埛搴旂敤鏈嶅姟涔熸病鏈夌洿鎺ヤ緷璧栦笌鍏蜂綋鐨勪粨鍌ㄧ被锛屽悓鏍蜂篃鏄渚濊禆鍏舵帴鍙c傚瑰簲鐨勭敤鎴蜂粨鍌ㄧ被鐨勫疄鐜板備笅锛

鍥涖丄ngularJS鍓嶇瀹炵幇

Web鍓嶇鐨勫疄鐜板氨鏄閲囩敤AngularJS鏉ュ疄鐜帮紝骞朵笖閲囩敤妯″潡鍖栧紑鍙戞ā寮忋傚叿浣揥eb鍓嶇鐨勪唬鐮佺粨鏋勫備笅鍥炬墍绀猴細



浣跨敤AngularJS寮鍙戠殑Web搴旂敤绋嬪簭鐨勪唬鐮佷箣闂寸殑璋冪敤灞傛″拰鍚庣鍩烘湰涓鑷达紝涔熸槸瑙嗗浘椤甸潰鈥斺斻嬫帶鍒跺櫒妯″潡鈥斺斻嬫湇鍔℃ā鍧椻斺斻媁eb API鏈嶅姟銆

骞朵笖Web鍓嶇疌SS鍜孞S璧勬簮鐨勫姞杞介噰鐢ㄤ簡Bundle鐨勬柟寮忔潵鍑忓皯璇锋眰璧勬簮鐨勬℃暟锛屼粠鑰屽姞蹇椤甸潰鍔犺浇鏃堕棿銆傚叿浣揃undle绫荤殑閰嶇疆锛

棣栭〉 Index.cshtml


浜斻佽繍琛屾晥鏋

浠嬬粛瀹屽墠鍚庣鐨勫疄鐜颁箣鍚庯紝鎺ヤ笅鏉ヨ╂垜浠鐪嬩笅鏁翠釜椤圭洰鐨勮繍琛屾晥鏋滐細



鍏銆佹荤粨

鍒版わ紝鏈鏂囩殑鎵鏈夊唴瀹归兘浠嬬粛瀹屼簡锛屽敖绠℃湰鏂囩殑AngularJS鐨勫簲鐢ㄩ」鐩杩樻湁寰堝氬畬鍠勭殑鍦版柟锛屼緥濡傛病鏈夌紦鍐茬殑鏀鎸併佹病鏈夊疄鐜拌诲啓鍒嗙伙紝娌℃湁瀵逛竴浜汚PI杩涜屽帇鍔涙祴璇曠瓑銆備絾AngularJS鍦ㄥ疄闄呴」鐩涓鐨勫簲鐢ㄥ熀鏈鏄杩欐牱鐨勶紝澶у跺傛灉鍦ㄩ」鐩涓鏈夐渶瑕佺敤鍒癆ngularJS锛屾eソ浣犱滑鍏鍙哥殑鍚庡彴鍙堟槸.NET鐨勮瘽锛岀浉淇℃湰鏂囩殑鍒嗕韩鍙浠ユ槸涓涓寰堝ソ鐨勫弬鑰冦傚彟澶栵紝鍏充簬鏋舵瀯鐨勮捐′篃鍙浠ュ弬鑰冩垜鐨勫彟涓涓寮婧愰」鐩锛歄nlineStore鍜孎astWorks銆

❸ 怎么在angularjs的config中使用service

Angular中有几种不同类型的services。每一种都有自己的独特用法。

需要记住的非常重要的一点是service总是一个单体,无论是哪种类型的service。
注释:单体是一种设计模式,它限制了每一个类仅能够实例化为一个对象。无论我们在什么地方注入我们的service,将永远使用同一个实例。
例子:
app.constant('fooConfig',{
config1: true,
config2: "Default config2" });

Constant是一个非常有用的service,它经常被用来在指令中提供默认配置。因此如果你正在创建一个指令,并且你想要在给指令传递可选参数的同时进行一个默认配置,一个Constant就是一个好办法。
作为一个constant,我们放入其中的值将不会改变。Contant service 基本上回事一个基本类型的值或者是一个对象。
例子:
app.value('fooConfig',{
config1: true,
config2: "Default config2 but it can change" });

一个value service有点像是一个constant但是它是可以被改变的。它也经常被用在一个指令上面,来进行配置。一个value service有点像是一个factory service的缩小版,它经常用来保存值但是我们不能在其中对值进行计算。
我们可以使用angular对象的extend方法来改变一个value service:
app = angular.mole("app", []);

app.controller('MainCtrl', function($scope, fooConfig) { $scope.fooConfig = fooConfig;
angular.extend(fooConfig, {config3: "I have been extended"});
});

app.value('fooConfig', {
config1: true,
config2: "Default config2 but it can changes" });
例子:
app.factory('foo', function() { var thisIsPrivate = "Private"; function getPrivate() { return thisIsPrivate;
} return {
variable: "This is public",
getPrivate: getPrivate
};
});
// or..
app.factory('bar', function(a) { return a * 2;
});

Factory service是最普遍使用的service。它同样也非常容易理解。

一个Factory是一个能够返回任何数据类型的service。对于你如何创建它并没有什么可选项,你仅仅需要在其中返回一些东西即可。

正如前面所说的,所有的service类型都是单体,因此如果我们在一个地方修改了foo.variable,其他的地方也会相应的发生改变。
例子:
app.service('foo', function() { var thisIsPrivate = "Private"; this.variable = "This is public"; this.getPrivate = function() { return thisIsPrivate;
};
});

Service service 和factory差不多。它们之间的区别在于service会接收一个构造器,因此当你第一次使用它的时候,它将会自动运行newFoo()来实例化一个对象。一定要记住如果你在其他的地方也使用了这个service,它将返回同一个对象。
事实上,上面的代码和下面的代码等价:
app.factory('foo2', function() { return new Foobar();
}); function Foobar() { var thisIsPrivate = "Private"; this.variable = "This is public"; this.getPrivate = function() { return thisIsPrivate;
};
}

Foobar是一个类,我们在首次使用它的时候在我们的factory中将它实例化然后将它返回。和service一样,Foobar将只会实例化一次然后下次当我们再次使用factory时它将返回同一个实例。
如果我们已经有了一个类,并且我们想将它用在service中,我们只需要编写如下的代码:
app.service('foo3',Foobar);

Provider是factory的加强版。事实上,上一个例子中的factory代码等价于下面的provider代码:
app.provider('foo', function() { return { $get: function() { var thisIsPrivate = "Private"; function getPrivate() { return thisIsPrivate;
} return {
variable: "This is public",
getPrivate: getPrivate
};
}

};

});

一个provider中应当由一个$get函数,其中的内容就是我们想要注入我们应用中的部分,因此当我们将foo注入一个控制器时,我们实际上注入的是$get函数。
既然factory如此简单,那我们为什么还要使用provider呢?因为我们可以在config阶段配置一个provider。因此我们可以编写下面的代码:
app.provider('foo', function() { var thisIsPrivate = "Private"; return {

setPrivate: function(newVal) { thisIsPrivate = newVal;
}, $get: function() { function getPrivate() { return thisIsPrivate;
} return {
variable: "This is public",
getPrivate: getPrivate
};
}

};

});

app.config(function(fooProvider) { fooProvider.setPrivate('New value from config');
});

在这里我们将thisIsPrivate移到了我们的$get函数的外面,然后我们创建了一个setPrivate来在一个config函数中修改thisIsPrivate。为什么我们需要这样做?这难道不比在factory中添加setter要容易吗?除此之外,还有另外一个原因。

我们想要注入一个特定的对象但是我们想要提供一种方式来根据我们的需求进行一些配置。例如:一个service包含了一个使用jsonp的资源,我们想要配置具体使用的URL,或者我们想要使用一个第三方的service比如restangular来允许我们根据我们的需求来进行配置。

要注意到我们在config函数中放入的是nameProvider而不是name。在这里,我们实际上还是对name进行配置。

看到这里我们其实已经意识到了我们已经在应用中进行过一些配置了,像是$routeProvider以及$locationProvider,两者分别用来配置我们的路由了html5模式。

那么现在已经决定要使用前面的 foo service,但是其中还是缺少一个你想要的greet函数。你可以修改factory吗?答案是不行!但是你可以装饰它:
app.config(function($provide){ $provide.decorator('foo',function($delegate){ $delegate.greet = function(){ return "Hello, I am a new function of 'foo'";
}
});
});

$provide是Angular用来在内部创建我们的service的东西。如果我们想要使用它的话可以手动来使用它或者仅仅使用在我们的模块中提供的函数(我们需要使用$provide来进行装饰)。$provide有一个函数,decorator,它让我们可以装饰我们的service。它接收我们想要装饰的service的名字并且在回调函数中接收一个$delegate来代表我们实际上的service实例。

在这里我们可以做一切我们想要的事情来装饰我们的service。在上面的例子中,我们为我们原来的service添加了一个greet函数。接着我们返回了修改后的service。

经过修改以后,现在我们的factory中已经有了一个叫做greet的函数。

装饰一个service的能力是非常实用的,尤其是当我们想要使用第三方的service时,此时我们不需要将代码复制到我们的项目中,而只需要进行一些修改即可。

注意:constant service不能被装饰。

我们的services都是单体但是我们可以创建一个单体factory来创建新的实例。在你深入之前,记住Angular中的服务都是单体并且我们不想改变这一点。但是,在极少数的情况下你需要生成一个新的实例,你可以像下面这样做:
function Person(json){ angular.extend(this,json);
}

Person.prototype = {
update: function(){ this.name = "Dave"; this.country = "Canada";
}
};

Person.getById = function(id){ return new Person({
name: "Jesus",
country: "Spain" });
};
app.factory('personService',function(){ return {
getById: Person.getById
};
});

在这里我们创建了一个Person对象,它接收一些json数据来初始化对象。然后我们在我们的原型(原型中的函数可以被Person的实例所用)中创建了一个函数,并且在Person上直接创建了一个函数(就像是类函数一样)。

因此现在我们拥有了一个类函数,它将基于我们提供的id来创建一个新的Person对象,并且每一个对象都可以自我更新。现在我们仅仅需要创建一个能够使用它的service。

当每次我们调用personService.getById时,我们都在创建一个新的Person对象,因此你可以在不同的控制器中使用这个service,即便当factory是一个单体,它也能生成新的对象。

Service是Angular中最酷的特性之一。我们可以使用很多方法来创造它们,我们仅仅需要找到符合我们需求的方法然后实现它。

❹ angularjs中run方法有什么作用

run方法用于初始化全局的抄数据,仅对全局作用域起作用。

举个栗子吧:

<script type="text/javascript">
var m1 = angular.mole('myApp',[]);
m1.run(['$rootScope',function($rootScope){
$rootScope.name = 'hello';
}]);
console.log( m1 );
</script>

❺ 如何在 AngularJS 中对控制器进行单元测试

Instant Karma

Karma 是来Angular团队针对JavaScript开发的一个测试运行框架。它很方便的实现了自动执行测试任务从而替代了繁琐的手工操作(好比回归测试集或是加载目标测试的依赖关系)Karma 和Angular的协作就好比花生酱和果冻.
只需要在Karma中定义好配置文件启动它,接下来它就会在预期的测试环境下的自动执行测试用例。你可以在配置文件中制定相关的测试环境。angular-seed,是我强烈推荐的可以快速实施的方案。在我近期的项目中Karma 的配置如下:

mole.exports = function(config) {
config.set({
basePath: '../',

files: [
'app/lib/angular/angular.js',
'app/lib/angular/angular-*.js',
'app/js/**/*.js',
'test/lib/recaptcha/recaptcha_ajax.js',
'test/lib/angular/angular-mocks.js',
'test/unit/**/*.js'
],

exclude: [
'app/lib/angular/angular-loader.js',
'app/lib/angular/*.min.js',
'app/lib/angular/angular-scenario.js'
],

autoWatch: true,

frameworks: ['jasmine'],

browsers: ['PhantomJS'],

plugins: [
'karma-junit-reporter',
'karma-chrome-launcher',
'karma-firefox-launcher',
'karma-jasmine',
'karma-phantomjs-launcher'
],

junitReporter: {
outputFile: 'test_out/unit.xml',
suite: 'unit'
}

})
}

这个跟angular-seed的默认配置类似只不过有以下几点不同:
需要更改浏览器从Chrome 转到PhantomJS, 这样每次跳转时无需再打开新的浏览器窗口,但在OSX系统会有窗口延迟。所以这个插件还有浏览器设置都做了更改。
由于我的应用需要引用Google的Recaptcha服务因此添加了依赖的recaptcha_ajax.js小文件。这个小配置就像在Karma的配置文件中添加一行代码那么简单。
autoWatch确实是个很酷的设置,它会让Karma在有文件更改时自动回归你的测试用例。你可以这样安装Karma:

用Jasmine设计测试用例
当使用Jasmine----一种行为驱动开发模式的JavaScript测试框架为Angular设计单元测试用例时大部分 的资源都已可获取。
这也就是我接下来要说的话题。
如果你要对AngularJS controller做单元测试可以利用Angular的依赖注入dependency injection 功能导入测试场景中controller需要的服务版本还能同时检查预期的结果是否正确。例如,我定义了这个controller去高亮需要导航去的那个页签:

app.controller('NavCtrl', function($scope, $location) {
$scope.isActive = function(route) {
return route === $location.path();
};
})

如果想要测试isActive方法,我会怎么做呢?我将检查$locationservice 变量是否返回了预期值,方法返回的是否预期值。因此在我们的测试说明中我们会定义好局部变量保存测试过程中需要的controlled版本并在需要时注入到对应的controller当中。然后在实际的测试用例中我们会加入断言来验证实际的结果是否正确。整个过程如下:

describe('NavCtrl', function() {
var $scope, $location, $rootScope, createController;

beforeEach(inject(function($injector) {
$location = $injector.get('$location');
$rootScope = $injector.get('$rootScope');
$scope = $rootScope.$new();

var $controller = $injector.get('$controller');

createController = function() {
return $controller('NavCtrl', {
'$scope': $scope
});
};
}));

it('should have a method to check if the path is active', function() {
var controller = createController();
$location.path('/about');
expect($location.path()).toBe('/about');
expect($scope.isActive('/about')).toBe(true);
expect($scope.isActive('/contact')).toBe(false);
});
});
使用整个基本的结构,你就能设计各种类型的测试。由于我们的测试场景使用了本地的环境来调用controller,你也可以多加上一些属性接着执行一个方法清除这些属性,然后再验证一下属性到底有没有被清除。

那么要是你在调用$httpservice请求或是发送数据到服务端呢?还好,Angular提供了一种
$httpBackend的mock方法。这样的话,你就能自定义服务端的响应内容,又或是确保服务端的响应结果能和单元测试中的预期保持一致。
具体细节如下:

describe('MainCtrl', function() {
var $scope, $rootScope, $httpBackend, $timeout, createController;
beforeEach(inject(function($injector) {
$timeout = $injector.get('$timeout');
$httpBackend = $injector.get('$httpBackend');
$rootScope = $injector.get('$rootScope');
$scope = $rootScope.$new();

var $controller = $injector.get('$controller');

createController = function() {
return $controller('MainCtrl', {
'$scope': $scope
});
};
}));

afterEach(function() {
$httpBackend.();
$httpBackend.verifyNoOutstandingRequest();
});

it('should run the Test to get the link data from the go backend', function() {
var controller = createController();
$scope.urlToScrape = 'success.com';

$httpBackend.expect('GET', '/slurp?urlToScrape=http:%2F%2Fsuccess.com')
.respond({
"success": true,
"links": ["www.google.com", "angularjs.org", "amazon.com"]
});

// have to use $apply to trigger the $digest which will
// take care of the HTTP request
$scope.$apply(function() {
$scope.runTest();
});

expect($scope.parseOriginalUrlStatus).toEqual('calling');

$httpBackend.flush();

expect($scope.retrievedUrls).toEqual(["www.google.com", "angularjs.org", "amazon.com"]);
expect($scope.parseOriginalUrlStatus).toEqual('waiting');
expect($scope.doneScrapingOriginalUrl).toEqual(true);
});
});
正如你所见,beforeEach call其实都很类似,唯一不同的是我们是从injector获取$httpBackend而并非直接获取。即使如此,创建不同的测试时还会有一些明显的不同之处。对初学者来说,会有一个afterEachcall 方法来确保$httpBackend在每次用例执行后不会有明显的异常请求。如果你观察一下测试场景的设置和$httpBackend方法的应用就会会发现有那么几点不是那么直观的。

实际上调用$httpBackend的方法也算是简单明了但还不够——我们还得在传值给$scope.$apply的方法中把调用封装到实际测试中的$scope.runTest方法上。这样在$digest被触发后才能处理HTTP请求。而如你所见直到我们调用$httpBackend.flush()方法后$httpBackend才会被解析,这也就保证了我们能在调用过程中去验证返回的结果是否正确(在上面的示例中,controller的$scope.属性将被传递给调用者,我们也因此能实时监控)
接下来的几行代码都是在调用过程中检测$scopethat属性的断言。很酷吧?
提示:在某些单元测试中,用户习惯把没有$的范围标记为变量。这个在Angular文档中并没有强制要求或是过分强调,只是我在使用中为了提高可读性和一致性才使用$scopelike这种方式。

结论

也许这就是我做起来对其他人而言只是自然而然能做到的事情之一,但是学习使用Angular编写单元测试一开始对我而言确实是相当痛苦的。我发现自己对如何开始的理解大多来自互联网上各种博客文章和资源的拼拼凑凑,没有真正一致或明确的最佳实践,而是通过自然而然随意的选择。我想针对我最终得到的成果提供一些文档,以帮助那些也许还在坑里面挣扎的其他人,毕竟他们只是想要编写代码而已,而非不得不去了解Angular和Jasmine中所有的怪异特性和独特用法

阅读全文

与angularjs控制器初始化相关的资料

热点内容
哪个编程平台好学 浏览:259
xp系统文件夹共享权限设置 浏览:532
搜索文件格式 浏览:162
兴趣班编程猫是什么 浏览:195
编程i3和i5哪个好 浏览:856
mac用什么打开pdf文件 浏览:903
手机百度查看过的网站怎么删除 浏览:620
applemusic支持哪些文件格式 浏览:79
全省统一编程是什么意思 浏览:501
现在的编程课有哪些 浏览:820
网站页面如何转文档 浏览:179
译官大数据 浏览:619
华为手机中录音文件保存在哪里 浏览:854
网络技术公司的组织架构 浏览:330
大数据视频收视率 浏览:973
2017新版本赵云技能 浏览:776
java大数据教程pdf 浏览:927
木槿花西月锦绣小说在哪个app看 浏览:263
qrcode二维码生成工具 浏览:18
电脑上的ps忘记安装在哪个文件夹 浏览:781

友情链接