我刚开始使用Angular
。我非常喜欢这个设计,测试它真的很不错。我无法做到的一件事就是测试asynchronous services
及其与controllers
的连接。
只是为了确保我确实理解了Angulars $q
,如果我的服务看起来像这样;
this.AsyncTask = function (params) {
var deferred = $q.defer();
doAsyncStuff(params, function () {
if (iAmReady) {
deferred.resolve("Success");
}
});
return deferred.promise;
};
在我看来,这基本上做了以下几点。做异步的东西并返回一个promise(它正在处理异步的东西)。在某个时刻处理事件时,"通知"承诺异步任务完成并返回一些值。现在在我的控制器中我会这样做。
MyService.AsyncTask(params).then(function (value) {
if (value) {
$scope.success = value;
}
});
这里控制器指示服务执行AsyncTask(带有一些参数),.then
告诉服务完成异步任务,控制器可以根据该结果做一些逻辑。 />
到目前为止一直很好,这实际上在制作中完全符合我的要求,但是我无法使用jasmine
对其进行单元测试。
我尝试了很多可能的解决方案(包括Angulars official example on that以及jasmines done
功能)但我似乎无法使其工作,这些是我面临的问题< / strong>:
expect
永远不会被调用(或者更准确地说,由于调试时结果是正确的,因此过早调用)done
(例如在.then
内)时,它总是超时并且永远不会被调用。 $rootScope.$apply
对我和问题1都没有做任何事情。所以如果你能给我一些关于如何做到这一点的提示,我会很高兴的。
答案 0 :(得分:0)
在不知道您描述的每个问题的测试代码的情况下,通常您可以像这样测试异步服务:
describe('service', function() {
// alter to match your module name
beforeEach(module('myApp.services'));
it('should test async calls', function (done) {
//inject your services
inject(function(MyService) {
MyService.AsyncTask({/*your params*/})
.then(function (result) {
expect(result).toBeDefined();
// add more tests
done();
}).catch(function (err) {
// don't forget this. If something goes wrong, you wanna know
// why and don't run into a non-saying timeout error
fail('Failure during AsyncTask: ' + err);
done(); // important so that the runner knows the test is over
// even if it failed
});
});
});
});
当您使用Jasmine 2.0运行异步测试时,需要在完成测试后调用done
方法。如果默认超时不足以进行测试,则可以为单个测试定义超时:
it('should ...', function(done) { ... }, 10000); // timeout set to 10 sec
关于您的问题的更多想法:如果doAsyncStuff
联系到服务器,您可能需要模拟它或在karma config中定义代理。在浏览器中观察运行测试的控制台,以获得更多线索。