2014-04-27 234 views
3

我有我的控制器$ rootScope。$的功能,监听用户登录

 $rootScope.$on('$firebaseSimpleLogin:login',function(e, authUser) { 
      User.findByUid(authUser.uid).then(function(user) { 

我嘲笑 '用户' 和 'login服务' 的服务。

beforeEach(inject(function($controller, $rootScope, $q) { 
    scope = $rootScope.$new(); 
    q = $q; 
    headerCtrl = $controller('headerCtrl', { 
     $scope: scope, 
     loginService: _loginService, 
     User: _userService 
    }); 
})); 

现在我想测试User.findByUid将被调用时,$渔获用户登录。所以我需要知道如何“模拟”这个$ on方法,所以我可以检查findByUid方法是否被调用。怎么样?我想是这样...

it('should call User.findByUid on $firebaseSimpleLogin:login', function() { 
    spyOn(scope, '$on'); 

      // here I need to probably trigger it somehow... 

      // and check or?... 
    expect(scope.$on).toHaveBeenCalled(); 
}); 

UPDATE https://gist.github.com/TrkiSF2/39315e7ea980cac6cc9f

SIDE问题

当我改变我CTRL代码:

 $rootScope.$on('$firebaseSimpleLogin:login',function(e, authUser) { 
      User.findByUid(authUser.uid); 
     }); 

我的模拟用户服务:

  findByUid: function(uid) { 
      console.log("dump"); 
     } 

而我的测试:

it('should call User.findByUid on $firebaseSimpleLogin:login', function() { 
    spyOn(_userService, 'findByUid'); 

    var authUser = { uid: 1 }; 
    scope.$emit('$firebaseSimpleLogin:login', authUser); 

    expect(_userService.findByUid).toHaveBeenCalled(); 
}); 

它的工作原理......但为什么没有“倾倒”在控制台消息,所以我可以肯定的测试中使用我的嘲笑代码,没有真正的一。 (可以说,我想可以肯定,如果有也不会执行一些DB查询...)

最后一个问题

如果我CTRL代码如下所示:

 $rootScope.$on('$firebaseSimpleLogin:login',function(e, authUser) { 
      User.findByUid(authUser.uid).then(function(user) { 

       User.setCurrentUser(user); 

我想检查是否也调用了User.setCurrentUser?什么是最好的方式来做到这一点?在一些单独的代码或以某种方式相同?

MAYBE回答我的问题?

我出于好奇这是什么会做只是尝试,我增加了新的方法,我的嘲笑用户对象:

 setCurrentUser: function(user) { 

     } 

我已经解决了我的承诺:

 findByUid: function(uid) { 
      defered = q.defer(); 
       defered.resolve({nick:'Trki'}); 
      return defered.promise; 
     }, 

然后,我更新了我测试

it('should call User.findByUid on $firebaseSimpleLogin:login', function() { 
    spyOn(_userService, 'findByUid').and.callThrough(); 
    spyOn(_userService, 'setCurrentUser'); 

    var authUser = { uid: 1 }; 
    scope.$emit('$firebaseSimpleLogin:login', authUser); 
    scope.$root.$digest(); 

    expect(_userService.findByUid).toHaveBeenCalled(); 
    expect(_userService.setCurrentUser).toHaveBeenCalled; 
}); 

它说成功!这是好方法吗?

回答

1

间谍上的用户模拟:

spyOn(_userService, 'findByUid').and.callThrough(); 

然后用$broadcast$emit手动调度事件(取决于你从调度哪个范围)。如果需要添加参数:

var authUser = { uid: 1 }; 
scope.$emit('$firebaseSimpleLogin:login', authUser); 

执行验证:

expect(_userService.findByUid).toHaveBeenCalled(); 

您需要使用and.callThrough()在这种情况下,因为你有一个then加入连锁这里:

User.findByUid(authUser.uid).then(function(user) { 

而且如果不通过你的模拟通话不会返回你已经定义的承诺:

findByUid: function(uid) { 
    defered = q.defer(); 
    return defered.promise; 
} 

它会尝试在undefined上执行then,因此“'undefined'不是对象”。

SIDE的问题 - 答案:

如果添加.and.callThrough();console.log("dump")应该执行。

如果不这样做,该呼叫将被拦截,有关该呼叫的信息将被保存,但该功能不会实际执行。

这意味着,如果您正在监视自己的嘲笑,您几乎总是希望使用callThrough(),因为它返回模拟数据。

这也意味着你并不总是需要自己的模拟器,因为你可以在你的服务上设置一个间谍,真正的实现将不会被执行,因为调用将被拦截。

然后,您可以使用and.returnValueand.callFake来返回或执行模拟逻辑。

+0

应该叫User.findByUid上$ firebaseSimpleLogin:登录失败 \t类型错误:“未定义”不是(评估“User.findByUid(authUser.uid)。然后”)的对象,但它有点怪怪的,因为这要求用户.findByUid函数来自控制器而不是来自模拟服务。 – EnchanterIO

+0

当我将您的代码更改为“spyOn(_userService,'findByUid').callThrough();”测试成功。但我有点困惑,为什么... – EnchanterIO

+0

文档。 http://jasmine.github.io/edge/introduction.html#section-Spies:_ and.callThrough仍然不清楚... – EnchanterIO