Angularjs 在angular应用程序中组织单元测试

Angularjs 在angular应用程序中组织单元测试,angularjs,unit-testing,karma-runner,Angularjs,Unit Testing,Karma Runner,测试依赖于其他模块的模块,以及其中的提供者和服务-可能。假设我们需要测试依赖于模块“B”的模块“A”: 完全不是coffeescript,而是为了简洁起见的伪代码:) 现在,假设我们有许多需要模拟的模块,以及许多服务和提供者。那么,如何将伪造的“B”部分转移到单独的文件中? 之后它们将如何使用?使用模块加载器(webpack、browserify)是很有可能的,但是如果没有它怎么办呢?使用角度能力和因果报应提供了什么 是否可以将整个模拟包装到angular模块中,并在每次加载之前加载到?是的,实

测试依赖于其他模块的模块,以及其中的提供者和服务-可能。假设我们需要测试依赖于模块“B”的模块“A”:

完全不是coffeescript,而是为了简洁起见的伪代码:)

现在,假设我们有许多需要模拟的模块,以及许多服务和提供者。那么,如何将伪造的“B”部分转移到单独的文件中? 之后它们将如何使用?使用模块加载器(webpack、browserify)是很有可能的,但是如果没有它怎么办呢?使用角度能力和因果报应提供了什么


是否可以将整个模拟包装到angular模块中,并在每次加载之前加载到

是的,实际上,使用Karma可以轻松地在angular中测试服务自己的模块

只要您的测试框架设置正确,并且所有需要的模块都加载到Karma中(检查Karma配置),那么这就相当简单了

下面的示例假定
FirstService
是您正在测试的服务,
SecondService
是FirstService依赖并与之交互的另一个服务

describe('FirstService', function () {
  var SecondService;

  beforeEach(module('FirstService'));

  beforeEach(inject(function (_SecondService_) {
    SecondService = _SecondService_;
    spyOn(SecondService, 'doSomethingElse');
  }));

  it('calls SecondService.doSomethingElse', function () {
    FirstService.doSomething();

    expect(SecondService.doSomethingElse).toHaveBeenCalled();
  });
});
按照第一行中的规定,将模块包含在每个
之前的
中。当包含模块时,不要使用方括号
[]
,因为这样会重新定义模块,并且希望按原样包含现有模块

尽管在导入模块时应省略方括号,但在最初创建FirstService模块时(例如,在
app.js
文件中,如果项目是这样设置的),应确保确实包含了SecondService作为依赖项:

angular.module('FirstService', ['SecondService'])
每个
之前的第二个
注入第二个服务模块。它已经在全球范围内可供注入,并且可以通过其模块名(带有前导和尾随下划线)访问,即
\u SecondService\u
。我已经将它分配给一个变量,以便它可以在
it
语句中使用,否则我需要在每个
it
语句中插入它,而不是在每个
之前插入

我正在使用Jasmine的
spyOn
创建一个间谍,以监视方法
doSomethingElse
以确保它已被调用。
spyOn
(方法名)的第二个参数应该有引号,但第一个参数不应该有引号,它应该是您刚刚为第二个服务定义的变量


示例单元测试测试调用
FirstService.doSomething()
调用
SecondService.doSomethingElse()

我仍然不明白。。。假设我正在测试一个依赖于
ui.router
模块的模块。我需要模拟用户界面。路由器的$stateProvider。我可以在我的SUT(我正在测试的模块)的相同规范文件中进行测试。但是,如果同样的逻辑(模仿$stateProvider)也需要在其他规范中使用呢。然后我需要把它放在一个单独的文件中。我不能只做像'angular.module('ui.router',[])这样的事情;模块(函数($provide){…etc`-这不起作用。我可以将模拟逻辑包装到其他模块中,比如说命名为“mocks”,然后使用angular.injector加载该模块,这是一个简单的方法。如果您试图访问当前状态,可以插入
$state
。description('FirstService',function(){var$state;beforeach(module('FirstService'));beforeach(inject(function($state){$state=$state;}));它('calls SecondService.doSomethingElse',function(){FirstService.doSomething();expect($state.current.name).toBe('login');});您试图从
$stateProvider
访问什么?我之前关于注入
$state
的评论的代码:
在每个之前(注入(函数($state){$state=$state})
并检查当前状态,如下所示:
expect($state.current.name).toBe('login');
angular.module('FirstService', ['SecondService'])