【问题标题】:Angular.js unit testing - trouble mocking $windowAngular.js 单元测试 - 模拟 $window 的麻烦
【发布时间】:2015-08-25 18:14:47
【问题描述】:

我制作了一个简单的 Angular 服务来与本地存储进行交互。它有一个 has 方法返回真/假,具体取决于密钥是否存在于本地存储中。

angular.module("jbLocalStorage", [])
.service("localStorageService", ["$window", function($window){

  this.has = function(key){
    console.log($window); //added to see what $window is referencing in unit test
    if ($window.localStorage.getItem(key) !== null){
      return true;
    } else {
      return false;
    }
  };
}]);

我在单元测试中模拟出 $window 时遇到了麻烦。单元测试似乎仍在访问全局窗口对象,而不是访问模拟。

这是我对此服务的单元测试。我尝试使用getItem 函数创建一个模拟$window 对象。

describe("Has function", function(){
  var localStorageService;

  beforeEach(module('jbLocalStorage'), function($provide){
    $provide.value('$window', {
      localStorage : {
        getItem : function(key){
          if (key === "shape") {return "triangle";} else {return null;}
        },
      },
    });
  });

  beforeEach(inject(function(_localStorageService_){
    localStorageService = _localStorageService_;
  }));

  it("should return true if key is found in local storage", function(){
    expect(localStorageService.has("shape")).toEqual(true);
  });
});

我的测试失败了,因为测试似乎在查看全局 window 对象并没有找到“形状”,而不是查看模拟并找到“形状”。

我知道它正在这样做,因为服务中的 console.log 行表明它仍在引用全局 windowobject,而不是 mock。

我做错了什么?为什么我的模拟不起作用?

【问题讨论】:

  • 这是我收到的错误:Error: Expected false to equal true.

标签: javascript angularjs unit-testing


【解决方案1】:

$provide 应该被注入到模块函数中。

在这里查看小提琴 - http://jsfiddle.net/eitanp461/bvsp41yz/

describe("Has function", function(){
  var localStorageService;

  beforeEach(module('jbLocalStorage', function($provide){
    $provide.value('$window', {
      localStorage : {
        getItem : function(key){
          if (key === "shape") {return "triangle";} else {return null;}
        },
      },
    });
  }));

  beforeEach(inject(function(_localStorageService_){
    localStorageService = _localStorageService_;
  }));

  it("should return true if key is found in local storage", function(){
    expect(localStorageService.has("shape")).toEqual(true);
    expect(localStorageService.has("wat?")).toBeFalsy();
  });
});

【讨论】:

  • 谢谢!我花了很长时间试图了解您的答案与我最初写的内容之间的区别。我终于发现您删除了第一个 before each 语句中的括号。我不小心将两个参数传递给beforeEach,而我应该只传递一个带有两个参数的`module()'。
【解决方案2】:

我做了类似的事情并让它发挥作用。在查看了我的代码后,我相信我有一个适合您的解决方案。

我认为您需要先致电$provide,然后再致电module('jbLocalStorage')。我相信正在发生的事情是$window 服务正在通过module 调用注入到您的代码中,然后您正在修改已经注入的值。

所以这应该有效:

beforeEach(function() {
    module(function($provide) {
        $provide.value('$window', {
            localStorage : {
                getItem : function(key){
                    if (key === "shape") {return "triangle";} else {return null;}
                },
            },
        });
    });
    module('jbLocalStorage');
});

【讨论】:

  • 我刚试了一下,得到:TypeError: $provide.value is not a function。好像找不到$provide。
  • 如果我尝试 ` beforeEach(inject(function($provide){'... 它也会抛出一个错误:Error: [$injector:unpr] Unknown provider: $provideProvider <- $provide
  • 我的测试组织方式与你的略有不同。我将示例更改为更接近我的完成方式。
猜你喜欢
  • 1970-01-01
  • 2015-08-24
  • 1970-01-01
  • 2017-06-27
  • 2011-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多