我将尝试测试Angular服务,该服务通过
这样的服务可能如下所示:
$document
服务对DOM进行一些操作,并使用Jasmine进行测试。
简单来说,它会将某些指令附加到<body>
元素上。这样的服务可能如下所示:
(function(module) {
module.service('myService', [
'$document',
function($document) {
this.doTheJob = function() {
$document.find('body').append('<my-directive></my directive>');
};
}
]);
})(angular.module('my-app'));
我想这样测试它
describe('Sample test' function() {
var myService;
var mockDoc;
beforeEach(function() {
module('my-app');
// Initialize mock somehow. Below won't work indeed, it just shows the intent
mockDoc = angular.element('<html><head></head><body></body></html>');
module(function($provide) {
$provide.value('$document', mockDoc);
});
});
beforeEach(inject(function(_myService_) {
myService = _myService_;
}));
it('should append my-directive to body element', function() {
myService.doTheJob();
// Check mock's body to contain target directive
expect(mockDoc.find('body').html()).toContain('<my-directive></my-directive>');
});
});
那么问题是,创建这样的模拟的最佳方法是什么?
使用真实的document
进行测试会给我们带来很多麻烦,每次测试后都需要清理,并且看起来不是正确的方法。
我也尝试在每个测试之前创建一个新的真实文档实例,但最终遇到了不同的失败。
创建以下对象并检查whatever
变量可以工作,但看起来非常丑陋。
var whatever = [];
var fakeDoc = {
find: function(tag) {
if (tag == 'body') {
return function() {
var self = this;
this.append = function(content) {
whatever.add(content);
return self;
};
};
}
}
}
我感觉我在这里缺少重要的东西,做了一些非常错误的事情。
非常感谢任何帮助。
doTheJob
时向document
添加一些内容,然后通过调用cleanup
方法删除添加的元素。如果某个清理操作失败,则所有依赖于文档内容的其他测试都可能失败。恢复每个测试后文档的原始状态可能是可能的,但这可能与原始问题一样棘手。 - Alexander Nyrkov$document.find('body').html('')
(如果有jQuery,则为$document.find('body').empty()
)即可将所有内容恢复到原始状态。我会更新答案以说明这一点。 - Michael Benfordbody
标签内,但它只是带有所有必要内容的<script>
标签。由于这些脚本已经在第一个测试运行时加载完毕,从body
中删除它们似乎不会影响其余的测试。但我同意你的观点,干涉不属于自己的事情并不是一个好主意。 - Michael Benford