【问题标题】:How do I mock $location.host() in angularjs tests?如何在 angularjs 测试中模拟 $location.host()?
【发布时间】:2013-06-12 23:42:55
【问题描述】:

我创建了一个包含环境信息的Env 服务,我目前正在使用$location.host() 来确定我所处的环境。如何在我的测试中模拟它?

我读过https://groups.google.com/forum/?fromgroups#!topic/angular/F0jFWC4G9hI,但它似乎不起作用,例如:

describe("Env (environment) service", function() {

  var Env;

  beforeEach(module('App'));

  beforeEach(inject(
    ['Env', function(e) {
      Env = e;
    }]
  ));

  describe("for staging", function() {
    beforeEach(inject(function($location, $rootScope) {
      $location.host("http://staging-site.com");
      $rootScope.$apply();
    }));

    it("returns envrionment as staging", function() {
      expect(Env.environment).toEqual("staging");
    });

    it("returns .isStaging() as true", function() {
      expect(Env.isStaging()).toBeTruthy();
    });
  });
});

我也尝试过$browser 变体,但这也不起作用。有什么想法吗?

【问题讨论】:

标签: javascript testing angularjs mocking


【解决方案1】:

最好的方法是使用间谍恕我直言:http://tobyho.com/2011/12/15/jasmine-spy-cheatsheet/

// inject $location
spyOn($location, "host").andReturn("super.domain.com");
var host = $location.host();
alert(host) // is "super.domain.com"
expect($location.host).toHaveBeenCalled();

jasmine 2.0 及更高版本的语法已更改如下

// inject $location
spyOn($location, "host").and.returnValue("super.domain.com");
var host = $location.host();
alert(host) // is "super.domain.com"
expect($location.host).toHaveBeenCalled();

【讨论】:

  • jasmine 2.0 及更高版本的语法已更改,您应该使用 .and.returnValue()
【解决方案2】:

我也遇到过类似的问题,并且使用过 $injector 服务。 (我不知道这是否是最简单的解决方案,但它对我有用:))

由于在测试期间不能依赖 $location,我准备了自己的模拟。 首先,您需要创建一个工厂方法。 (如果您愿意,也可以选择服务或提供商 - 请参阅 https://gist.github.com/Mithrandir0x/3639232 进行比较):

function locationFactory(_host) {
  return function () {
    return {
      /* If you need more then $location.host(), add more methods */
      host: function () {
        return _host;
      }
    };
  };
}

然后在你创建你的'Env'之前,用这个$location mock 喂注入器:

module(function ($provide) {
  $provide.factory('$location', locationFactory('http://staging-site.com'));
});

现在,每次您在代码中访问 $location 时都会注入您的模拟,因此它会返回您需要的任何内容。 更多关于 $provide 方法的内容在angular docs

希望这对您将来有所帮助。

更新:我看到一个地方你可能出错了(或者至少在我的解决方案中会出错)。似乎您正在启动“Env”模块(我猜它会立即计算数据)并且只有在此之后您才更改 $location - 这可能已经太晚了。

【讨论】:

    【解决方案3】:

    文档中有一个很好的例子:https://docs.angularjs.org/guide/services

    您要确保在实例化服务之前使用$provide。我喜欢在测试用例中使用$injector,首先确定位置,然后实例化服务。

      var mockLocation;
    
      beforeEach(function() {
        // control the $location.host() function
        // which we fake in the testcases.
        mockLocation = {
          host: jasmine.createSpy()
        };
        module(function($provide) {
          $provide.value('$location', mockLocation);
        });
      });
    

    然后

      describe('staging server:', function() {
        beforeEach(function() {
          // mockLocation.host.andReturn('http://staging-site.com'); // jasmine 1.x
          mockLocation.host.and.returnValue('http://staging-site.com');
        });
    
        it('returns envrionment as staging', inject(function($injector) {
          Env = $injector.get('Env');
          expect(Env.environment).toEqual('staging');
        }));
      });
    

      describe('production server:', function() {
        beforeEach(function() {
          // mockLocation.host.andReturn('prod.example.com'); // jasmine 1.x
          mockLocation.host.and.returnValue('prod.example.com');
        });
    
        it('returns envrionment as production', inject(function($injector) {
          Env = $injector.get('Env');
          expect(Env.environment).toEqual('production');
        }));
      });
    

    【讨论】:

      【解决方案4】:

      这是另一种模拟 $location 的方法,使用 Sinon.js

          locationMock = {
              path: sinon.spy()
          };
      

      还有一个示例断言:

      locationMock.path.should.be.calledWith('/home');
      

      【讨论】:

        猜你喜欢
        • 2013-12-13
        • 1970-01-01
        • 2013-07-13
        • 1970-01-01
        • 2014-02-08
        • 1970-01-01
        • 2017-09-25
        • 1970-01-01
        • 2013-06-09
        相关资源
        最近更新 更多