【问题标题】:Angular JS Testing with Karma Jasmine使用 Karma Jasmine 进行 Angular JS 测试
【发布时间】:2017-06-10 03:52:33
【问题描述】:

我有一个这样的示例路线

  angular
        .module('appRouter',['ui.router'])
        .config(function($stateProvider,$urlRouterProvider){
            $stateProvider
                .....
                .....
                .state('settings.account',{
                    url:'/account',
                    templateUrl:'templates/account.html',
                    controller:function(resolveData){
                        console.log(resolveData);
                    },
                    resolve:{
                        resolveData : function($http){
                            var root = 'https://jsonplaceholder.typicode.com';
                            return $http.get(root+'/posts/1').then(function(response){

                                return response.data;
                            });
                        }
                    }
                });

            .....

这只是一个测试 URL,我可以在线获取示例 JSON 数据

https://jsonplaceholder.typicode.com/posts/1

我想测试一下状态。

  beforeEach(function(){
        module('appRouter');
    });

    beforeEach(inject(function(_$rootScope_,_$injector_,_$state_,_$httpBackend_,$templateCache){
        $rootScope = _$rootScope_;
        $state = _$state_;
        $injector = _$injector_;
        $httpBackend = _$httpBackend_;
        $templateCache.put('templates/account.html','');
    }));

   it('should resolve "resolveData"',function(){
        const state = $state.get('settings.account');
        const resolveFn = state.resolve.resolveData;

                $httpBackend.whenGET('https://jsonplaceholder.typicode.com/posts/1').respond(function(){
        return [
            200,{
                "userId": 1,
                "id": 1,
                "title": "...",
                "body": "..."
        }]
    });

    $httpBackend.expectGET('https://jsonplaceholder.typicode.com/posts/1');

    $injector.invoke(resolveFn);

    $httpBackend.flush();

    expect($injector.annotate(resolveFn)).toEqual(['$http']);

    console.log(angular.mock.dump($scope));

    expect($scope.resolveData).toEqual({
         "userId": 1,
         "id": 1,
         "title": "...",
         "body": "..."
     });

但这失败了。话说

1) should resolve "resolveData"
     UI Routerer Config For Account
     Expected undefined to equal Object({ userId: 1, id: 1, title: '...', body: '...' }).
    at Object.<anonymous> (test/controllers/main-controller-spec.js:114:36)

我做错了什么?

更新

console.log(angular.mock.dump($scope)); 给出以下内容

请帮忙。

【问题讨论】:

  • 我认为您提出的原始问题(在编辑之前)具有原始错误的价值。这个新的错误信息应该是一个新问题。它们都是两个独立的问题,应该单独处理。
  • 我不明白你想在这里测试什么。我的意思是:测试应该检查您的代码是否正在执行您期望它执行的某些逻辑。但是相反(据我所知)您的测试检查您是否可以从某些请求中获取一些 json。那不是测试的目的。可能是服务器端测试的好目的。相反,我建议您在“resolve”中调用一些服务(只需通过注入一些服务并调用其方法之一来替换 $http 调用),现在您可以测试是否调用服务以响应“state.go”,并且如果使用正确的参数调用服务。 (这是我的看法)

标签: javascript angularjs unit-testing karma-jasmine


【解决方案1】:

原始错误:

should resolve "resolveData"
UI Routerer Config For Account
TypeError: Cannot read property 'get' of undefined
  at resolveData (app/appRouter.js:25:41)
  at Object.<anonymous> (test/controllers/main-controller-spec.js:97:9)

我做错了什么?

您在单元测试中调用resolveFn()。该函数被定义为需要$http 服务,并且该调用未通过$http 服务(如fingerpich 所述)。

要更正此问题,请允许 Angular 使用 $injector.invoke(resolveFn) 处理依赖注入。

通过plunk 了解此操作。请注意,测试确实由于不同的原因而失败。但是,(如果我正确理解规则)这是一个不同的问题,应该用不同的问题来回答(如果您需要更多帮助)。

附注:当网站(不是单元测试)在浏览器中打开时,我希望它能够工作,因为 Angular 将 $http 依赖项注入到分配给 resolveData 的函数中。

看看answer,它也引用了fingerpich提到的博客。

这是我在了解unit testing AngularJS 时发现的一个有用的博客。

【讨论】:

  • 我尝试了同样的方法,但对我来说没有效果。当我期望 $scope.resolveData 匹配 JSON 数据时,它说 Expected undefined to equal Object({ userId: 1, id: 1, title: ...。我做错了什么?
  • 您是否仍然收到错误should resolve "resolveData"... TypeError: Cannot read property 'get' of undefined...?如果没有,您的原始问题应该得到解决,评论中提到的错误将属于新问题。
  • 也许稍微轻推将有助于解决新错误:在测试结束时的 expect 语句之前添加 console.log(angular.mock.dump($scope));。之后,查看.then() 如何与$injector.invoke() 调用here 一起使用(我在答案中包含了此链接)。
  • console.log(angular.mock.dump($scope)); 给出错误。查看更新。
  • 此外,$injector.invoke($state.get('settings.account').resolve['resolveData']) .then(function(res){console.log(res.data);}); 给了我undefined。我尝试按照您提到的答案中提到的步骤进行操作。
【解决方案2】:
should resolve "resolveData"
UI Routerer Config For Account
TypeError: Cannot read property 'get' of undefined
 at resolveData (app/appRouter.js:25:41)
 at Object.<anonymous> (test/controllers/main-controller-spec.js:97:9)

要解决这个问题,你应该将$http 传递给resolveData 函数。

resolveFn($http); 

但最好写像this这样的测试

【讨论】:

  • 很抱歉,但这里显示 `ReferenceError: $http is not defined`。请看一下。
  • 我做到了。它没有说出我提到的错误。如何克服?
猜你喜欢
  • 1970-01-01
  • 2020-04-10
  • 1970-01-01
  • 2015-12-07
  • 1970-01-01
  • 2016-08-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多