Ввод проблемы
Я пытаюсь использовать unit test службу AngularJS, которая обертывает Facebook
JavaScript SDK FB
объект; однако тест не работает,
и я не смог понять, почему. Кроме того, код службы
когда я запускаю его в браузере вместо JasmineJS
тест, выполните Тест-драйв кармы.
Я тестирую асинхронный метод, используя Angular promises через $q
объект. У меня есть тесты, настроенные для асинхронного запуска, используя Жасмин
1.3.1 методы асинхронного тестирования, но waitsFor()
функция никогда не возвращает true
(см. тестовый код ниже), это просто тайм-аут
через 5 секунд. (Карма еще не поставляется с API асинхронного тестирования Jasmine 2.0).
Я думаю, это может быть потому, что метод then()
обещание никогда не срабатывает (у меня есть console.log()
, чтобы показать
это), хотя я звоню $scope.$apply()
, когда асинхронный
метод возвращает, чтобы Angular знал, что он должен запускать дайджест
цикл и вызвать обратный вызов then()
... но я мог ошибаться.
Это вывод ошибки, полученный при запуске теста:
Chrome 32.0.1700 (Mac OS X 10.9.1) service Facebook should return false
if user is not logged into Facebook FAILED
timeout: timed out after 5000 msec waiting for something to happen
Chrome 32.0.1700 (Mac OS X 10.9.1):
Executed 6 of 6 (1 FAILED) (5.722 secs / 5.574 secs)
Код
Это мой unit test для службы (см. встроенные комментарии, которые объясняют, что я нашел до сих пор):
'use strict';
describe('service', function () {
beforeEach(module('app.services'));
describe('Facebook', function () {
it('should return false if user is not logged into Facebook', function () {
// Provide a fake version of the Facebook JavaScript SDK `FB` object:
module(function ($provide) {
$provide.value('fbsdk', {
getLoginStatus: function (callback) { return callback({}); },
init: function () {}
});
});
var done = false;
var userLoggedIn = false;
runs(function () {
inject(function (Facebook, $rootScope) {
Facebook.getUserLoginStatus($rootScope)
// This `then()` callback never runs, even after I call
// `$scope.$apply()` in the service :(
.then(function (data) {
console.log("Found data!");
userLoggedIn = data;
})
.finally(function () {
console.log("Setting `done`...");
done = true;
});
});
});
// This just times-out after 5 seconds because `done` is never
// updated to `true` in the `then()` method above :(
waitsFor(function () {
return done;
});
runs(function () {
expect(userLoggedIn).toEqual(false);
});
}); // it()
}); // Facebook spec
}); // Service module spec
И это моя служба Angular, которая тестируется (см. встроенные комментарии, которые объясняют, что я нашел до сих пор):
'use strict';
angular.module('app.services', [])
.value('fbsdk', window.FB)
.factory('Facebook', ['fbsdk', '$q', function (FB, $q) {
FB.init({
appId: 'xxxxxxxxxxxxxxx',
cookie: false,
status: false,
xfbml: false
});
function getUserLoginStatus ($scope) {
var deferred = $q.defer();
// This is where the deferred promise is resolved. Notice that I call
// `$scope.$apply()` at the end to let Angular know to trigger the
// `then()` callback in the caller of `getUserLoginStatus()`.
FB.getLoginStatus(function (response) {
if (response.authResponse) {
deferred.resolve(true);
} else {
deferred.resolve(false)
}
$scope.$apply(); // <-- Tell Angular to trigger `then()`.
});
return deferred.promise;
}
return {
getUserLoginStatus: getUserLoginStatus
};
}]);
Ресурсы
Вот список других ресурсов, на которые я уже рассмотрел попытайтесь решить эту проблему.
-
Это объясняет, как использовать promises в Angular, а также пример использования модульного теста, который использует promises (обратите внимание на объяснение причин, почему
$scope.$apply()
необходимо вызвать для запускаthen()
). -
Примеры тестирования асинхронного жасмина
- Jasmine.Async: Создание асинхронного тестирования с жасмином сосать меньше
-
Тестирование асинхронного Javascript с Jasmine 2.0.0
Они приводят примеры использования асинхронных методов Jasmine 1.3.1 для проверки объектов, реализующих шаблон Promise. Они немного отличаются от шаблона, который я использовал в своем собственном тесте, который моделируется после примера, который приходит непосредственно из Jasmine 1.3.1 асинхронная тестовая документация.
-
Ответы StackOverflow
- Promise callback не вызван в Angular JS
- angularjs - обещание никогда не разрешалось в контроллере
- AngularJS promises не запускается при возврате из службы
Резюме
Обратите внимание, что я знаю, что есть уже другие библиотеки Angular для SDK для JavaScript JavaScript, например:
Мне сейчас не интересно использовать их, потому что я хотел научиться писать службу Angular. Поэтому, пожалуйста, держите ответы ограниченными, помогая мне исправить проблемы в моем коде, вместо того, чтобы предлагать, чтобы я использовал чужую.
Итак, с учетом сказанного, знает кто, почему мой тест не работает?