AngularJS Promise Callback Not Trigged in JasmineJS Test

前端 未结 3 631
挽巷
挽巷 2021-02-05 01:02

Problem Intro

I\'m trying to unit test an AngularJS service that wraps the Facebook JavaScript SDK FB object; however, the test isn\'t working, and I have

3条回答
  •  执念已碎
    2021-02-05 01:18

    TL;DR

    Call $rootScope.$digest() from your test code and it'll pass:

    it('should return false if user is not logged into Facebook', function () {
      ...
    
      var userLoggedIn;
    
      inject(function (Facebook, $rootScope) {
        Facebook.getUserLoginStatus($rootScope).then(function (data) {
          console.log("Found data!");
          userLoggedIn = data;
        });
    
        $rootScope.$digest(); // <-- This will resolve the promise created above
        expect(userLoggedIn).toEqual(false);
      });
    });
    

    Plunker here.

    Note: I removed run() and wait() calls because they're not needed here (no actual async calls being performed).

    Long explanation

    Here's what's happening: When you call getUserLoginStatus(), it internally runs FB.getLoginStatus() which in turn executes its callback immediately, as it should, since you've mocked it to do precisely that. But your $scope.$apply() call is within that callback, so it gets executed before the .then() statement in the test. And since then() creates a new promise, a new digest is required for that promise to get resolved.

    I believe this problem doesn't happen in the browser because of one out of two reasons:

    1. FB.getLoginStatus() doesn't invoke its callback immediately so any then() calls run first; or
    2. Something else in the application triggers a new digest cycle.

    So, to wrap it up, if you create a promise within a test, explicitly or not, you'll have to trigger a digest cycle at some point in order for that promise to get resolved.

提交回复
热议问题