2015-11-01 54 views
5

如何模拟出一个简单的工厂在AngularJs中返回一个Karma单元测试中的静态数据?Angularjs测试返回静态数据的简单工厂

我有这个简单的工厂,对于例如起见返回静态数据:

angular.module('conciergeApp.services') 
     .factory('CurrentUser', function() { 
     return { 
      id: 1, 
      hotel_id: 1, 
     } 
     }); 

我想知道怎么写了Karma测试呢?

到目前为止,我有这样的代码,但ID不工作:

describe('ReplyCtrl', function() { 

    beforeEach(module('conciergeApp')); 

    beforeEach(module(function($provide) { 
     $provide.service('CurrentUser', function() { 
      return 1; 
     }); 
    })); 

    //Getting reference of the mocked service 
    var mockUtilSvc; 

    inject(function(CurrentUser) { 
     mockUtilSvc = CurrentUser; 
    }); 

    beforeEach(inject(function($rootScope, $controller) { 
     scope = $rootScope.$new(); 
     ctrl = $controller('ReplyCtrl', { 
      $scope: scope 
     }); 
    })); 

    it('should return value from mock dependency', inject(function(mockUtilSvc) { 
     expect(mockUtilSvc()).toEqual(1); 
    })); 

}); 

这是我已经得到该错误消息:

Firefox 41.0.0 (Mac OS X 10.10.0) ReplyCtrl should return value from mock dependency FAILED 
    Error: [$injector:unpr] Unknown provider: mockUtilSvcProvider <- mockUtilSvc 

回答

4

1)您有inject在错误的地方。您正在测试it中指定注射功能,只需将其删除即可。

it('should return value from mock dependency', inject(function(mockUtilSvc) { 
    expect(mockUtilSvc()).toEqual(1); 
})); 

将成为

it('should return value from mock dependency', function() { 
    expect(mockUtilSvc()).toEqual(1); 
}); 

2)现在的问题是,mockUtilSvc是服务实例,并按照您的定义不是一个功能,还可根据您的模拟,你需要将其定义为工厂(即,您将返回1作为工厂的值,而不是new)。

beforeEach(module(function($provide) { 
    $provide.factory('CurrentUser', function() { 
     return 1; 
     //If you expect factory to be a function then you need to return a function returning 1 here 
    }); 
})); 

expect(mockUtilSvc).toEqual(1); 

3)你可能也写为:

$provide.value('CurrentUser', 1); //Provide the instance here right away 

4)你的第一个inject也错了地方。您只是在运行它,但不运行并在每次运行规范时分配实例。 before Each迭代你需要的服务实例的值设置为变量,即:

beforeEach(inject(function(CurrentUser) { 
    mockUtilSvc = CurrentUser; 
})); 

的试验例:

describe('ReplyCtrl', function() { 
    var mockData = { 
      id: 1234, 
      hotel_id: 1, 
     }, mockUtilSvc, scope, ctrl ; 


    beforeEach(module('conciergeApp', function($provide) { 
     $provide.value('CurrentUser', mockData); 
    })); 

    beforeEach(inject(function(CurrentUser, $rootScope, $controller) { 
     mockUtilSvc = CurrentUser; 
     scope = $rootScope.$new(); 
     ctrl = $controller('ReplyCtrl', { 
      $scope: scope 
     }); 
    })); 

    it('should return value from mock dependency', function() { 
     expect(mockUtilSvc.id).toEqual(mockData.id); 
    }); 
}); 

Demo

注:有其他的方式来嘲笑并注入模拟。例如,在这种情况下,您并不需要使用$provide.value。相反,你可以创建你的模拟对象和控制器实例化过程中通过它,你那边有完全控制权传递依赖,象下面这样:

ctrl = $controller('ReplyCtrl', { 
      $scope: scope, 
      CurrentUser: mockUtilSvc 
    }); 

在更复杂的服务的情况下,有方法,你可以创建模拟像这个。

mockSvc = jasmin.createSpyObj('MyService', ['method1', 'method2']); 
    mockSvc.method1.and.returnValue($q.when(mockData)); //Simulating a promise returned from an $http call in the method. 
+1

Hist第一个'inject'也出错了。他应该在'beforeEach'前面加上' – Phil

+0

@Phil True,我在步骤4中提到过它,可能不是很清楚。让我更新它。谢谢。 – PSL

+0

@PSL很好的答案,并感谢您的详细解释。这样可以更清楚地了解这里发生的事情以及如何设置此模拟服务测试的逻辑。谢谢! –