简体   繁体   English

将服务注入Angular单元测试时出现Unknown Provider错误

[英]Getting Unknown Provider error when injecting a Service into an Angular unit test

I'm fairly new to Angular and have reviewed all the similarly related questions on Stack Overflow but none have helped me. 我对Angular很新,并且已经回顾了Stack Overflow上所有类似相关的问题,但没有人帮助过我。 I believe I have everything set up correctly but am still getting an 'Unknown Provider' error when attempting to inject a service into a unit test. 我相信我已经正确设置了所有内容,但在尝试将服务注入单元测试时仍然出现“未知提供程序”错误。 I have laid out my code below - hopefully someone can spot an obvious error! 我在下面列出了我的代码 - 希望有人能发现一个明显的错误!

I define my modules in a seperate .js file like this: 我在一个单独的.js文件中定义我的模块,如下所示:

angular.module('dashboard.services', []);
angular.module('dashboard.controllers', []);

Here is where I define a service called EventingService (with logic removed for brevity): 这里我定义了一个名为EventingService的服务(为简洁起见,删除了逻辑):

angular.module('dashboard.services').factory('EventingService', [function () {
    //Service logic here
}]);

Here is my controller that uses the EventingService (this all works fine at runtime): 这是我使用EventingService的控制器(这在运行时都可以正常工作):

angular.module('dashboard.controllers')
    .controller('Browse', ['$scope', 'EventingService', function ($scope, eventing) {
        //Controller logic here
}]);

Here is my unit test - its the line where I attempt to inject the EventingService that causes an error when I run the unit test: 这是我的单元测试 - 它是我尝试注入EventingService的行,当我运行单元测试时会导致错误:

describe('Browse Controller Tests.', function () {
    beforeEach(function () {
        module('dashboard.services');
        module('dashboard.controllers');
    });

    var controller, scope, eventingService;

    beforeEach(inject(function ($controller, $rootScope, EventingService) {
        scope = $rootScope.$new();
        eventingService = EventingService

        controller = $controller('Browse', {
            $scope: scope,
            eventing: eventingService
        });
    }));


    it('Expect True to be True', function () {
        expect(true).toBe(true);
    });
});

When I run the test I get this error: 当我运行测试时,我收到此错误:

Error: Unknown provider: EventingServiceProvider <- EventingService 错误:未知提供者:EventingServiceProvider < - EventingService

I have ensured that my jasmine specrunner.html file has all the necessary source files (this is an Asp.Net MVC project): 我确保我的jasmine specrunner.html文件具有所有必需的源文件(这是一个Asp.Net MVC项目):

<!-- Include source files here... -->
@Scripts.Render("~/bundles/jquery")
<script type="text/javascript" src="@Url.Content("~/Scripts/angular.js")"></script>  
<script type="text/javascript" src="@Url.Content("~/Scripts/angular-mocks.js")"></script>                 

<script type="text/javascript" src="@Url.Content("~/App/scripts/app.js")"></script>                       <!-- Angular modules defined in here -->
<script type="text/javascript" src="@Url.Content("~/App/scripts/services/eventing.js")"></script>         <!-- My Eventing service defined here -->


<script type="text/javascript" src="@Url.Content("~/App/scripts/controllers/browse.js")"></script>        <!-- My Browse controller defined here -->

<!-- Include spec files here... -->
<script type="text/javascript" src="@Url.Content("~/App/tests/browse.js")"></script>                      <!-- The actual unit test here -->

I just can not fathom why Angular is throwing this error complaining about my EventingService. 我只是无法理解为什么Angular会抛出这个错误抱怨我的EventingService。 My controller works fine at runtime - it's just when I try to test it that I am getting an error so I am curious as to whether I have screwed something up with the mocking/injection. 我的控制器在运行时运行良好 - 就在我尝试测试它时我得到了一个错误,所以我很好奇我是否用模拟/注入搞砸了。

The Angular help on testing is rubbish so I am stumped at present - any help or suggestions anyone can give would be very appreciated. Angular对测试的帮助是垃圾,所以我目前感到难过 - 任何人都可以给予任何帮助或建议将非常感激。 Thanks. 谢谢。

I just ran into this and solved it by switching to getting the service using the $injector explicitly: 我刚刚遇到这个并通过切换到使用$ injector显式获取服务来解决它:

var EventingService, $rootScope;
beforeEach(inject(function($injector) {
  EventingService = $injector.get('EventingService');
  $rootScope = $injector.get('$rootScope');
}));

I wish I could tell you why this works and why the simple 我希望我能告诉你为什么这个有用,为什么这么简单

beforeEach(inject(function(EventingService) {   ....  }));

does not, but I don't have the time to investigate the internals. 不,但我没有时间调查内部。 Always best to use one coding style and stick to it. 总是最好使用一种编码风格并坚持下去。

This style is better in that the name of the variable that you use in your tests is the correct name of the Service. 这种样式更好,因为您在测试中使用的变量名称是服务的正确名称。 But it is a bit verbose. 但它有点冗长。

There is another angular magic feature that uses strange variable names like $rootScope but I don't like the hacky look of that. 还有另一个角度魔术功能,使用奇怪的变量名称,如$ rootScope,但我不喜欢它的hacky外观。

Note that the most of the time people get this error because they didn't include the modules: 请注意,大多数时候人们会收到此错误,因为它们不包含模块:

beforeEach(module('capsuling'));
beforeEach(module('capsuling.capsules.services'));

If your controllers (defined under dashboard.controllers module) depend on some services which are enclosed in different module ( dashboard.services ) than you need to reference the dependency modules in your module signature: 如果您的控制器(在dashboard.controllers模块下定义)依赖于包含在不同模块( dashboard.services )中的某些服务,而不是您需要引用模块签名中的依赖项模块:

angular.module('dashboard.services', []);
angular.module('dashboard.controllers', ['dashboard.services']);

While this question is fairly old i lost significant time solving a problem similar to this one, ie: 虽然这个问题相当陈旧,但我在解决与此问题类似的问题时失去了大量时间,即:

Error: Unknown provider: SomeServiceProvider <- SomeService

Hence, i'm leaving here another possible cause to this issue. 因此,我将离开这里另一个可能的原因来解决这个问题。 Hopefully, it would helpful to someone. 希望它对某人有帮助。

In my case, i had in my project two modules with the exactly same name but with different dependencies being created, ie, two different .js files with: 在我的例子中,我在我的项目中有两个模块具有完全相同的名称,但创建了不同的依赖项,即两个不同的.js文件:

angular.module('moduleName', [dependencies]))

From angular documentation: 从角度文档:

Passing one argument retrieves an existing angular.Module, whereas passing more than one argument creates a new angular.Module 传递一个参数将检索现有的angular.Module,而传递多个参数会创建一个新的angular.Module

Conclusion : It turns out that what was being injected in the test was the module with the wrong dependencies. 结论 :事实证明,在测试中注入的是具有错误依赖性的模块。 Removing the second argument from the module that was erroneously being created solved the problem. 从错误创建的模块中删除第二个参数解决了该问题。

Have you tried defining an additional module that depends on your other aggregated modules like so: 您是否尝试过定义一个依赖于其他聚合模块的附加模块,如下所示:

angular.module( 'dashboard', [ 'dashboard.services', 'dashboard.controllers' ] )

So you can in the beforeEach specify the one module that has both submodules defined in it like so: 所以你可以在beforeEach中指定一个模块,其中包含两个子模块,如下所示:

describe('Browse Controller Tests.', function () {
    beforeEach(function () {
        module('dashboard');
    });

    var controller, scope, eventingService;

    beforeEach(inject(function ($controller, $rootScope, EventingService) {
        scope = $rootScope.$new();
        eventingService = EventingService

        controller = $controller('Browse', {
            $scope: scope,
            eventing: eventingService
        });
    }));


    it('Expect True to be True', function () {
        expect(true).toBe(true);
    });
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM