【经验】karma
1.beforeEach(inject(){...})中的代码会在beforeEach所在的describe中的每一个it(包括子describe中的it)前执行一次。
2.假如it不是写在describe中而是写在另一个it中则it中的内容不会被执行,且beforeEach不会执行。同理inject不是写在beforeEach中也不会被执行(可以写在it中执行)。
可能这里是使用了队列,在describe中执行it()时往队列里添,而写在it中的it在被执行时队列已经不接受加入了。
3.inject可以写在it中,甚至能写成it('', inject(...))
4.每个inject会重新运行一次run。也会重新生成一次$rootScope
5.关于karma的伪装响应。
使用$httpBackend.when(...).respond(200, data)来返回data。
假如要将本地html等文件作为上述data返回呢?
1. 首先需要利用$templateCache服务,本服务允许$http服务缓存经过XHR的模板请求。当一个模板被取到了,它的内容就会存储在$templateCache中,用模板路径做参数获取。
获取方式:$templateCache.get('xx.html')
2. 问题是如何将本地的xx.html放到$templateCache里呢?
我们写代码固然可以通过$templateCache.put('xx.html', ...)来往里面放内容,但本地的文件需要将模板转换成可在测试中使用的ng模块。
解决方案为使用karma-ng-html2js-preprocessor包来做转换工作。
[以上参考 《AngularJS权威教程》 19.14.7 p268]
首先需要安装包:
$ npm install --save-dev karma-ng-html2js-preprocessor
然后需要修改karma.conf.js:
files: [
'**/*.html'
],
preprocessors: {
'**/*.html': ['ng-html2js']
},
ngHtml2JsPreprocessor: {
moduleName: 'templates' // 这个是模块名字,随意取,
cacheIdFromPath: function(filepath){
return filepath // 这里获取到的filepath,是在上面files里定义的路径。然而这个路径与【被测试脚本】里所用的路径,可能因为根目录的不同而有差异。所以可以在这里做处理转成与测试脚本一样的路径,这样在【测试代码】里就能用这个路径获取到html了,即$templateCache('xxx'),xxx与被测试脚本的路径一致。
},
stripPrefix: ''
}
然后在test.js里先写:
beforeEach(module('templates'))
beforeEach(module('mainApp'))
【注意,一定要先加载templates模块,再加载你的模块。如果反过来,而你的模块中run中动态编译指令,又使用了$digest要立即渲染,这时会直接需要获取模板文件,但由于templates模块未加载无法获取文件,会报错:Error: Unexpected request: GET test/myDirective.html】
【也许是由于模板直接写到$templateCache里,所以不需要通过设置$httpBackend.when来伪装响应,更不需要$httpBackend.flush()】
然后这时伪装响应就能在收到响应时返回文件
$httpBackend.when('GET', 'test/myDirective.html').respond(200, $templateCache.get('test/myDirective.html'))
【注意$httpBackend.when必须在被测试文件发起请求前设置】
在it中冲刷请求:
it('发送请求', function(){
$httpBackend.flush()
})
6. $httpBackend.flush()貌似只能使用一次。
it('1', function(){
$httpBackend.when(...).respond(...);$httpBackend.flush();
})
it('2', function(){
$httpBackend.when(...).respond(...);$httpBackend.flush();
})
这样会导致2里的when无法返回。改成以下则可以:
it...$http...respond(...)
it...$http...respond(...)
it...$httpBackend.flush()
7.$http的使用方法对$httpBackend.when有影响
$httpBackend.when如下:
$httpBackend.when('GET','/js/apps/main/tpl/questionEntry.html',function(){
console.log('a')
return true
})
.respond(200,$templateCache.get('/js/apps/main/tpl/questionEntry.html'))
而使用$http({method: 'GET', url:...})时,能按理console;使用$http.get('...')时,则不能console
8.假如请求的url后面有时间戳,怎么才能在$httpBackend里获取到data呢?这里似乎从某个环节开始,都不会将时间戳作为data处理,所以导致when的第三个参数无法被调用。
解决方案如下:
$httpBackend.when('GET', {
test: function(url){
var str = '/js/apps/main/tpl/questionEntry.html'
return url.indexOf(str) != -1
}
})
.respond(200,$templateCache.get('/js/apps/main/tpl/questionEntry.html'))
请求使用directive、$http都可以发送。
9.在做inject注入时,如果多次注入,要注意每次所获取到的服务都是全新的。所以当第二个inject里的服务与第一个inject里的服务混用时会产生问题。