我在我的控制器$ rootScope。$ on函数中监听用户登录
$rootScope.$on('$firebaseSimpleLogin:login',function(e, authUser) {
User.findByUid(authUser.uid).then(function(user) {
我嘲笑'用户'和'loginService'服务。
beforeEach(inject(function($controller, $rootScope, $q) {
scope = $rootScope.$new();
q = $q;
headerCtrl = $controller('headerCtrl', {
$scope: scope,
loginService: _loginService,
User: _userService
});
}));
现在我想测试一下,当$ catch用户登录时,会调用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();
});
更新 https://gist.github.com/TrkiSF2/39315e7ea980cac6cc9f
侧面问题
当我将我的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();
});
它有效...但是为什么控制台中没有“转储”消息,所以我可以确定测试使用的是我的模拟代码,而不是真正的代码。 (假设我确定如果有......那么它将不会执行某些数据库查询。)
上一个问题
如果我的ctrl代码如下所示:
$rootScope.$on('$firebaseSimpleLogin:login',function(e, authUser) {
User.findByUid(authUser.uid).then(function(user) {
User.setCurrentUser(user);
我想检查一下是否也调用了User.setCurrentUser?最好的方法是什么?在一些单独的代码中或以某种方式相同?
可能会回答我的问题吗?
我只是从好奇心中尝试了这将做什么,我为我的模拟用户对象添加了新方法:
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;
});
它说成功!这是好方法吗?
答案 0 :(得分: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'不是对象”。
侧面问题 - 答案:
如果您添加.and.callThrough();
,console.log("dump")
应该执行。
如果不这样做,将会截获呼叫,保存有关呼叫的信息,但该功能实际上不会执行。
这意味着如果你在监视自己的嘲讽,你几乎总是想要使用callThrough()
,因为它会返回模拟数据。
这也意味着你并不总是需要自己的模拟,因为你可以在服务上设置间谍,并且不会执行真正的实现,因为调用将被截获。
然后,您可以使用and.returnValue
和and.callFake
返回或执行模拟逻辑。