如何在不重复超类测试的情况下测试Mocha中的Backbone子类?

时间:2015-05-11 19:10:58

标签: javascript unit-testing oop backbone.js mocha

假设我有几个Backbone模型,Rectangle和Triangle,每个都扩展了Polygon。

var Polygon = Backbone.Model.extend({
    defaults: {
       width: 100,
       height: 100,
       rotation: 0
    },
    rotate: function (degrees) {
       var oldRotation = this.get('rotation');
       var newRotation = (oldRotation + degrees) % 360;
       this.set('rotation', newRotation);
       return newRotation;
    }
});

var Rectangle = Polygon.extend({
    area: function (degrees) {
      return this.get('width') * this.get('height');
    }
});

var Triangle = Polygon.extend({
    area: function (degrees) {
      return this.get('width') * this.get('height') / 2;
    }
}

我想测试Rectangle和Triangle,并确保每个都正确地独立实现rotate,即使我知道(现在)它们都从Polygon继承了rotate的实现。

我不想做的是为Rectangle和Triangle创建单独的单元测试,它们几乎完全相同。在Mocha中,我如何为rotate编写测试并在三角形和矩形的单元测试中重用它?

这是我的单元测试。请注意副本“旋转45度”测试。

describe('A rectangle', function () {
  var r = new Rectangle({width: 50, height: 10, rotation: 90});
  it('correctly calculates its area', function () {
    expect(r.area()).to.equal(500);
  });
  it('rotates by 45 degrees', function () {
    expect(r.rotate(45)).to.equal(135);
  });
});

describe('A triangle', function () {
  var t = new Triangle({width: 50, height: 10, rotation: 90});
  it('correctly calculates its area', function () {
    expect(t.area()).to.equal(250);
  });
  it('rotates by 45 degrees', function () {
    expect(t.rotate(45)).to.equal(135);
  });
});

2 个答案:

答案 0 :(得分:1)

写完后答案很明显。我们可以创建一个函数来封装多边形的测试。

var describeAPolygon = function (name, p) {
    describe(name, function () {        
      it('rotates by 45 degrees', function () {
        expect(p.rotate(45)).to.equal(135);
      });
    });
};

然后在Rectangle和Triangle的测试中使用它。

describe('A rectangle', function () {
    var r = new Rectangle({width: 50, height: 10, rotation: 90});
    describeAPolygon('A rectangle', r);
    it('correctly calculates its area', function () {
      expect(r.area()).to.equal(500);
    });
});


describe('A triangle', function () {
    var t = new Triangle({width: 50, height: 10, rotation: 90});
    describeAPolygon('A triangle', t);
    it('correctly calculates its area', function () {
      expect(t.area()).to.equal(250);
    });
});

这是我能找到的最干净的解决方案。我很好奇是否有其他人解决了这个问题,并想出了不同的东西。

答案 1 :(得分:0)

我通常做的是:

describe('A rectangle', function () {
    var r = new Rectangle({width: 50, height: 10, rotation: 90});

    it('should be a polygon', function() {
      expect(r).to.be.an.instanceof(Polygon);
    });

    it('correctly calculates its area', function () {
      expect(r.area()).to.equal(500);
    });
});

describe('A triangle', function () {
    var t = new Triangle({width: 50, height: 10, rotation: 90});               

    it('should be a polygon', function() {
      expect(r).to.be.an.instanceof(Polygon);
    });

    it('correctly calculates its area', function () {
      expect(t.area()).to.equal(250);
    });
});

describe('A polygon', function() { 
    var p = new Polygon({width: 50, height: 10, rotation: 90});
    it('rotates by 45 degrees', function () {
      expect(p.rotate(45)).to.equal(135);
    });
});

如果您使用正确的OOP做法,那么您的Polygon类应该具有足够安全的方法和结构,以便任何扩展它的类都不能修改它。