I have a small Angular service that handles asynchronous rate-limiting of other functions, similar to this example. Since the main purpose of this class is to moderate asynchronous behaviors, I'd like to be able to test this service asynchronously - I won't be able to prove that this class is working with a purely synchronous test.
我有一个小的角度服务,它处理其他函数的异步限速,类似于这个示例。由于这个类的主要目的是适度的异步行为,所以我希望能够异步地测试这个服务——我无法证明这个类使用的是纯同步测试。
If I understand correctly, when Angular's ngMock
module is loaded, the built-in $timeout
service is replaced with a mocked version of $timeout
which allows tests to synchronously run functions that are ordinarily asynchronous. However, in this case, I'd like to use the real implementation of $timeout
instead of the mocked version.
如果我理解正确,那么在加载棱角的ngMock模块时,内置的$timeout服务将被替换为模拟版本的$timeout,该版本允许测试同步运行通常为异步的函数。但是,在这种情况下,我希望使用真正的$timeout实现,而不是模拟版本。
How can I inject the real implementation of $timeout
into my unit test?
如何将$timeout的实际实现注入到单元测试中?
Here's what my tests looks like currently (I'm writing my tests in TypeScript):
下面是我目前的测试(我正在用打字稿写测试):
describe('My Tests', () => {
let myService: MyService,
$timeout: ng.ITimeoutService;
beforeEach(() => {
inject(($injector) => {
// this gets me the mocked version of $timeout
$timeout = $injector.get('$timeout');
});
myService = new MyService($timeout);
jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000;
});
it('should pass', (done) => {
$timeout(50)
.then(() => {
// this is never called
expect(1).toBe(1);
})
.finally(done);
});
});
When I run this test, Karma complains that the test too took long because the mocked$timeout
service never actually kicks off its deferred timeout:
当我运行这个测试时,Karma会抱怨测试耗时太长,因为模拟的$timeout服务从来没有真正启动它的延迟超时:
Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
错误:Timeout . Async回调在jasmin . default_timeout_interval指定的超时内没有被调用。
1 个解决方案
#1
2
You need to call $timeout.flush(); to force all $timeout inside your controller to be released :
需要调用$timeout.flush();强制释放控制器内的所有$timeout:
it('a ctrl with $timeout inside', inject(function($timeout) {
var myCOntroller = $controller('Controller', { $scope: $scope });
// flush timeout(s) for all code under test.
$timeout.flush();
// this will throw an exception if there are any pending timeouts.
$timeout.verifyNoPendingTasks();
expect($scope.result).toBe("whatIexpect");
}));
// with your example
it('should pass', (done) => {
$timeout(50)
.then(() => {
// this is never called
expect(1).toBe(1);
})
.finally(done);
$timeout.flush();
});
Everything better explain here :)
这里有更好的解释:)
In addition, you should never use the real $timeout because it will REALLY slowing down your tests...
此外,您不应该使用真正的$timeout,因为它会真正地减慢您的测试……
#1
2
You need to call $timeout.flush(); to force all $timeout inside your controller to be released :
需要调用$timeout.flush();强制释放控制器内的所有$timeout:
it('a ctrl with $timeout inside', inject(function($timeout) {
var myCOntroller = $controller('Controller', { $scope: $scope });
// flush timeout(s) for all code under test.
$timeout.flush();
// this will throw an exception if there are any pending timeouts.
$timeout.verifyNoPendingTasks();
expect($scope.result).toBe("whatIexpect");
}));
// with your example
it('should pass', (done) => {
$timeout(50)
.then(() => {
// this is never called
expect(1).toBe(1);
})
.finally(done);
$timeout.flush();
});
Everything better explain here :)
这里有更好的解释:)
In addition, you should never use the real $timeout because it will REALLY slowing down your tests...
此外,您不应该使用真正的$timeout,因为它会真正地减慢您的测试……