2013-04-05 121 views
2

我有一個工廠,使用承諾來解析json文件。 它應該只在第一次解析該文件,並在再次調用時返回結果。AngularJS:需要幫助單元測試承諾的工廠

這裏是工廠

app.factory('getServerConfig', function ($q, $http, serverConfig) { 

    return function (fileName) { 
    var deferred = $q.defer(); 

    if (serverConfig.loaded) { 
     deferred.resolve("alreadyLoaded"); 
    } else { 
     $http.get(fileName).then(function (result) { 
     serverConfig.setConfig(result.data); 
     deferred.resolve("loaded"); 
     }, function (result) { 
     deferred.reject(); 
     }); 
    } 
    return deferred.promise; 
    }; 
}) 

我如何測試:

it('should say hallo to the World', inject(function(getServerConfig) { 
    var promiseResult; 

    getServerConfig("server-config.json").then(function (result) { 
     promiseResult = result; 
    }); 

    rootScope.$apply(); 
    expect(promiseResult).toBe('loaded'); 
})); 

不幸的是,它看起來喜歡promiseResult永遠不會設置。 這裏是用代碼plunker:http://plnkr.co/edit/uRPCjuUDkqPRAv07G5Nx?p=preview

回答

3

的問題是,$ httpBackend需要一個flush()(看看Flushing HTTP requests),這樣你就可以模仿你的測試$http異步行爲。

爲了解決這個問題,請存儲$httpBackend(或再次注入)的引用,並在請求完成後調用$ httpBack.flush()。

看:

it('should say hallo to the World', inject(function(getServerConfig, $httpBackend) { 
    var promiseResult; 

    getServerConfig("server-config.json").then(function (result) { 
    promiseResult = result; 
    }); 

    $httpBackend.flush(); 
    expect(promiseResult).toBe('loaded'); 
})); 

如果你要在你的大部分規格都使用$httpBackend,考慮將其存儲在一個局部變量,並將其設置在beforeEach

+0

啊謝謝。我沒有使用flush,但在beforeEach函數內部,這就是爲什麼它不起作用。謝謝! – 2013-04-05 13:40:56

+0

你會如何測試一個依靠這項服務的控制器?謝謝。 – Hcabnettek 2013-05-15 00:42:03

+0

測試您的控制器的最佳方法是嘲笑此服務並返回一個已知的承諾,您可以控制解析時間。如果你不想嘲笑它,只需要調用'$ httpBackend.flush()',並檢查控制器是否按照你期望的方式反應。創建一個新的問題(這是關閉這個主題),併發布一些代碼,所以我可以幫助你更多。 – 2013-05-15 13:19:11