Cra*_*ste 11 unit-testing promise jasmine angularjs
使用AngularJS,我试图对一个多次调用$ http的函数进行单元测试.
我的测试看起来像这样:
it('traverses over a hierarchical structure over multiple chained calls', function() {
myService.traverseTheStuff()
.then(function(theAggregateResult) {
// ...is never fulfilled
});
$httpBackend.flush();
});
Run Code Online (Sandbox Code Playgroud)
其他单调用测试将注册传递给.then()的回调,并在我调用.flush()后立即执行.
测试中的代码看起来像这样.
function traverseTheStuff(){
// This will make a call to $http to fetch some data
return getRootData()
// It is fulfilled at the end of the test when I $httpBackend.flush()
.then(function(rootData){
// Another call to $http happens AFTER $httpBackend.flush()
return getNextLevel(rootData.someReference);
})
// The second promise is never fulfilled and the test fails
.then(function(nextLevel){
return aggregateTheStuff(...);
});
}
Run Code Online (Sandbox Code Playgroud)
值得一提的是,每个单独的呼叫都是单独测试的.在这里,我想遍历一棵树,聚合一些数据和单元测试a)承诺链正确连接和b)聚合是准确的.将其展平为单独的离散调用已经完成.
Mic*_*mza 18
我是测试Angular的初学者,但是我已经设置了一个plnkr,用一个成功的"秒"然后/保证调用来测试与你的设置非常相似的设置
http://plnkr.co/edit/kcgWTsawJ36gFzD3CbcW?p=preview
以下代码片段是上述plnkr的略微简化版本.
我发现的关键点是
我注意到函数traverseTheStuff根本没有调用$ http/$ httpBackend.它只使用$ q promises中定义的函数,因此测试假设使用$ q,并注入它
var deferred1 = null;
var deferred2 = null;
var $q = null;
beforeEach(function() {
inject(function(_$q_) {
$q = _$q_;
});
});
beforeEach(function() {
deferred1 = $q.defer();
deferred2 = $q.defer();
}
Run Code Online (Sandbox Code Playgroud)异步调用的函数使用其promise返回值进行间谍/存根,其中promise在测试本身中创建,因此在测试traverseTheStuff时不会调用它们的实际实现
spyOn(MyService,'traverseTheStuff').andCallThrough();
spyOn(MyService,'getRootData').andReturn(deferred1.promise);
spyOn(MyService,'getNextLevel').andReturn(deferred2.promise);
spyOn(MyService,'aggregateTheStuff');
Run Code Online (Sandbox Code Playgroud)在测试中没有任何"then"的调用,只是为了"解析"测试中创建的promise,然后是$ rootScope.$ apply(),然后实际调用traverseTheStuff中的"then"回调,我们也可以测试一下
beforeEach(function() {
spyOn(deferred1.promise, 'then').andCallThrough();
});
beforeEach(function() {
deferred1.resolve(testData);
$rootScope.$apply(); // Forces $q.promise then callbacks to be called
});
it('should call the then function of the promise1', function () {
expect(deferred1.promise.then).toHaveBeenCalled();
});
Run Code Online (Sandbox Code Playgroud)必须解决每个承诺/ $ apply-ed以调用链中的下一个"then"函数.所以.要获得测试调用aggregateTheStuff(或者更确切地说,它的存根),还必须解析从getNextLevel存根返回的第二个promise:
beforeEach(function() {
deferred2.resolve(testLevel);
$rootScope.$apply(); // Forces $q.promise then callbacks to be called
});
it('should call aggregateTheStuff with ' + testLevel, function () {
expect(MyService.aggregateTheStuff).toHaveBeenCalledWith(testLevel);
});
Run Code Online (Sandbox Code Playgroud)上述所有问题都是它假定来自$ q和$ rootScope的某些行为.我是在理解单元测试这样的假设不应该做出这样的假设,以便真正只测试一点代码.我没有弄清楚如何解决这个问题,或者我是否误解了.
| 归档时间: |
|
| 查看次数: |
9574 次 |
| 最近记录: |