gpt4 book ai didi

AngularJS 单元测试 $rootScope.$on

转载 作者:行者123 更新时间:2023-12-03 08:06:31 24 4
gpt4 key购买 nike

我在我的 Controller $rootScope.$on 函数中监听用户登录

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

我 mock 了“User”和“loginService”服务。

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

现在我想测试当 $on 捕获用户登录时将调用 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) {

}

我兑现了我的 promise :

        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;
});

它说成功了!这样好吗?

最佳答案

监视用户模拟:

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) {

如果不让调用通过你的模拟将不会返回你定义的 promise :

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

它会尝试在未定义的情况下执行 then,因此“'undefined' 不是一个对象”。

附带问题 - 答案:

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

如果不这样做,调用将被拦截,有关调用的信息将被保存,但函数不会真正执行。

这意味着,如果您要监视自己的模拟,您几乎总是想使用 callThrough(),因为它会返回模拟数据。

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

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

关于AngularJS 单元测试 $rootScope.$on,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23322129/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com