【问题标题】:AngularJS: Testing with FabricJS/CanvasAngularJS:使用 FabricJS/Canvas 进行测试
【发布时间】:2014-02-07 23:39:55
【问题描述】:

你如何在指令和服务中为 FabricJS 之类的东西编写测试?

示例应用:http://fabricjs.com/kitchensink/

我一直在尝试,但如果没有非常糟糕的 hack,我并没有取得太大进展。 我想将此服务和指令集成到我的https://github.com/clouddueling/angular-common repo 中,以便其他人可以使用这个强大的库。

我的场景:

我正在尝试测试包含服务和指令的模块。这些将我的应用程序链接到 FabricJS。我在模拟包含 js 文件时创建的全局 fabric var 时遇到问题。我假设然后我监视包含织物画布的 var。

我只需要确认我的服务与结构正确交互。不过,我在模拟/存根织物时遇到了麻烦。

要赢得赏金:

  • 我可以与 Karma 一起使用的测试示例。

【问题讨论】:

    标签: angularjs canvas html5-canvas fabricjs


    【解决方案1】:

    这很困难,因为您没有提供要测试的代码。但是,为了可测试性,我会首先创建一个非常小的工厂来返回全局结构对象

    app.factory('fabric', function($window) {
      return $window.fabric;
    });
    

    然后可以通过注入一个模拟 $window 来测试这个工厂,并检查它的结构属性是否返回。

    describe('Factory: fabric', function () {
    
      // load the service's module
      beforeEach(module('plunker'));
    
      var fabric;
      var fakeFabric;
    
      beforeEach(function() {
        fakeFabric = {};
      });
    
      beforeEach(module(function($provide) {
        $provide.value('$window', {
          fabric: fakeFabric
        });    
      }));
    
      beforeEach(inject(function (_fabric_) {
        fabric = _fabric_;
      }));
    
      it('should return $window.fabric', function () {
        expect(fabric).toBe(fakeFabric);
      });
    
    });
    

    下面是使用该工厂的示例服务。

    app.service('MyFabricService', function(fabric) {
    
      this.newCanvas = function(element) {
        return new fabric.Canvas(element);
      }
    
      this.newRectangle = function(options) {
        return new fabric.Rect(options);
      }
    
      this.addToCanvas = function(canvas, obj) {
        return canvas.add(obj);
      }
    });
    

    然后您可以按如下方式测试这些方法。返回“新”对象的函数可以通过使用手动创建的 spy 创建一个模拟结构对象来测试,该对象将被称为构造函数,然后使用 instanceof 和 toHaveBeenCalledWith 来检查它是如何构造的:

    // Create mock fabric object
    beforeEach(function() {
      mockFabric = {
        Canvas: jasmine.createSpy()
      }
    });
    
    // Pass it to DI system
    beforeEach(module(function($provide) {
      $provide.value('fabric', mockFabric);    
    }));
    
    // Fetch MyFabricService
    beforeEach(inject(function (_MyFabricService_) {
      MyFabricService = _MyFabricService_;
    }));
    
    it('should return an instance of fabric.Canvas', function () {
      var newCanvas = MyFabricService.newCanvas();
      expect(newCanvas instanceof mockFabric.Canvas).toBe(true);
    }); 
    
    it('should pass the element to the constructor', function () {
      var element = {};
      var newCanvas = MyFabricService.newCanvas(element);
      expect(mockFabric.Canvas).toHaveBeenCalledWith(element);
    }); 
    

    可以通过使用“添加”间谍创建模拟画布对象来测试 addToCanvas 函数。

    var canvas;
    
    // Create mock canvas object
    beforeEach(function() {
      canvas = {
        add: jasmine.createSpy()
      }
    });
    
    // Fetch MyFabricService
    beforeEach(inject(function (_MyFabricService_) {
      MyFabricService = _MyFabricService_;
    }));
    
    it('should call canvas.add(obj)', function () {
      var obj = {};
      MyFabricService.addToCanvas(canvas, obj);
      expect(canvas.add).toHaveBeenCalledWith(obj);
    }); 
    

    这一切都可以在这个 Plunker http://plnkr.co/edit/CTlTmtTLYPwemZassYF0?p=preview 中看到

    【讨论】:

    • 这必须是一篇博文!我缺少的关键是您使用 $window 的第一个示例。永远不会想到这一点。
    【解决方案2】:

    为什么要为外部依赖编写测试?

    您首先假设 FabricJS 可以正常工作。测试它不是您的工作,即使是,您也必须进行字节流比较(这就是画布,将字节流解释为图像)。测试用户输入是完全不同的事情。查找 Selenium。

    然后您为为 FabricJS 生成正确输入的代码编写测试。

    【讨论】:

    • 他可能想为特定于应用程序的功能编写测试,而不是视觉表示。在 Fabric 中,我们有单元测试和功能测试。但是对于使用 Fabric 的应用程序,您可以测试 Fabric 和用户操作之间的功能层(例如单击那个按钮?画布上应该有 1 个文本对象;不是视觉上的,而是通过 Fabric 的对象模型以编程方式进行的 - canvas.item(0).type === 'text',等)
    • 是的,我的术语不是一流的,但这就是我所说的“为 FabricJS 输入”的意思,即 API 边界。
    • 您是否碰巧有一个示例来说明如何测试依赖于像fabric 这样的全局变量的服务?你如何嘲笑它,它看起来像什么?我只需要知道我的服务正在运行并正确调用 FabricJS 或其他任何内容。
    • 请在 cmets 中继续讨论或修改您的提交以回答问题。
    猜你喜欢
    • 2014-11-02
    • 2013-05-16
    • 2019-04-17
    • 2016-05-19
    • 2013-07-11
    • 1970-01-01
    • 1970-01-01
    • 2016-05-28
    • 1970-01-01
    相关资源
    最近更新 更多