【问题标题】:Angular/Karma: Mock Data UndefinedAngular/Karma:模拟数据未定义
【发布时间】:2015-11-22 19:54:34
【问题描述】:

我正在尝试创建一个单元测试来检查 GET 请求是否返回正确数量的项目,但我正在使用模拟数据来执行此操作。

我的测试如下所示:

test.js

describe('Customer Controller', function () {
    var controller;
    var customers = mockData.getMockCustomers(); // fake customers (5 customers)

    beforeEach(function() {
      bard.appModule('app');
      bard.inject('$controller', '$q', '$rootScope');

      var cs = {
        getCustomers: function() {
          return $q.when(customers);
        }
      };

      controller = $controller('customersCtrl', {
        CustomerService: cs
      });
    });

    it('should return 5 customers', function() {
      $rootScope.$apply();
      expect(controller.customers).to.have.length(5);
    });
});

我在运行测试时不断收到此错误:

TypeError: 无法读取未定义的属性“长度”

看起来controller.customers 出于某种原因以undefined 的身份回归。我是否正确地模拟了数据?

我对此很陌生,无法弄清楚我做错了什么。我什至不知道如何调试这样的问题。

感谢任何帮助。提前致谢!

更新

我的控制器如下所示:

function customersCtrl(dataservice) {
  var vm = this;
  vm.customers = [];

  fetchCustomers();

  function fetchCustomers() {
    return dataservice.getCustomers()
    .then(function(data) {
      vm.customers = data.data;
      return vm.customers ;
    });
  }
}

更新 2

我在测试中放置了一个 console.log,我的 customers 变量返回了 5 个似乎为空的对象。也许这就是问题所在?

【问题讨论】:

  • 只是出于兴趣,您是否更改了控制器的名称,或者您可能有复制和粘贴错误,您初始化 'scoreListCtrl' 而不是 'customersCtrl'
  • 是的,我已更改名称以发布此示例。

标签: angularjs unit-testing karma-runner karma-mocha


【解决方案1】:

你看过 $httpBackend 吗?如果那是您所期望的,那么单元测试实际上并不会影响您的数据库。您必须模拟自己的响应。

即:

$httpBackend.whenGET(/MyEndPoint).respond([{}, {}, {}]);

然后你可以测试长度为 3 或任何你想要的

【讨论】:

  • 我也会推荐这种方法,不仅你会发现它更容易使用,而且作为一种更标准的方法,你会发现很多关于如何做到这一点的文档。
  • 这就是我期望我的cs 做的事情。模拟返回的数据。我将如何重构我的代码以使用上面的 $httpBackend 方法?
  • 实际上,自从研究您的示例以来,最好继续模拟 CS,这就是您的依赖模拟。 CS 应该使用 $httpBackend 进行测试
  • 抱歉,我不确定你的意思。你能详细说明一下吗?
【解决方案2】:

新答案,推荐使用sinon spys

我使用 mocha 进行一些节点测试,使用 chai 和 sinon - 这是一个使用 sinon 存根的示例。

var sinon = require('sinon');

describe('Customer Controller', function () {
        var controller;
        var customers = mockData.getMockCustomers(); // fake customers (5 customers)

    beforeEach(function() {
      bard.appModule('app');
      bard.inject('$controller', '$q', '$rootScope');

      var deferred = $q.defer();
      deferred.resolve(customers);
      var cs = {
         fetchCustomers: sinon.stub().returns(deferred.promise)
      };

      controller = $controller('scoreListCtrl', {
        CustomerService: cs
      });
    });

    it('should return 5 customers', function() {
      $rootScope.$apply();
      expect(controller.customers).to.have.length(5);
    });
});

下面的原始答案,建议使用茉莉花间谍

你以前用过茉莉间谍吗?我会使用它们,这可能不会是您的复制和粘贴答案,但应该为您提供大致的进入方向。

describe('Customer Controller', function () {
    var controller;
    var customers = mockData.getMockCustomers(); // fake customers (5 customers)

    beforeEach(function() {
      bard.appModule('app');
      bard.inject('$controller', '$q', '$rootScope');

      var cs = {};
      var deferred = $q.defer();
      deferred.resolve(customers);
      spyOn(cs, 'fetchCustomers').and.returnValue(deferred.promise);

      controller = $controller('scoreListCtrl', {
        CustomerService: cs
      });
    });

    it('should return 5 customers', function() {
      $rootScope.$apply();
      expect(controller.customers).to.have.length(5);
    });
});

你可以在这里查看更多关于茉莉花间谍的信息:http://jasmine.github.io/2.0/introduction.html

【讨论】:

  • 我用的是 Mocha 而不是 Jasmine。
  • 更新了关于sinon spie的回答,给出了代码示例
猜你喜欢
  • 2015-02-10
  • 1970-01-01
  • 1970-01-01
  • 2023-04-07
  • 2023-03-11
  • 1970-01-01
  • 2014-05-21
  • 1970-01-01
  • 2016-12-23
相关资源
最近更新 更多