admin管理员组

文章数量:1208153

My tests fails for the following reason:

ReferenceError: Can't find variable: moving_canvas_context in file (line 5)

I understand the reason the test is failing. It doesn't understand the variable since it is defined in a separate JavaScript file. However, it is declared globally and works in reality.

How do I write a jasmine test for this clear_canvas function?

JavaScript Canvas_Actions:

(function() {
  window.Canvas_Actions = (function() {
    function Canvas_Actions() {}
    Canvas_Actions.prototype.clear_canvas = function() {
      moving_canvas_context.clearRect(0, 0, moving_canvas.width, moving_canvas.height);
      main_canvas_context.drawImage(window.background_image, 0, 0, main_canvas.width, main_canvas.height);
      return window.canvas_objects = [];
    };
    return Canvas_Actions;
  })();
}).call(this);

Jasmine Test for Canvas_Actions:

(function() {
  describe('Canvas Actions', function() {
    return describe('clear_canvas', function() {
      return it('clears the canvases and deletes all objects', function() {
        var actions;
        jasmine.getFixtures().fixturesPath = "../spec/javascript/fixtures";
        loadFixtures("canvas_fixture.html");
        actions = new Canvas_Actions();
        actions.clear_canvas();
        return expect(canvas_objects).toEqual([]);
      });
    });
  });
}).call(this);

My tests fails for the following reason:

ReferenceError: Can't find variable: moving_canvas_context in file (line 5)

I understand the reason the test is failing. It doesn't understand the variable since it is defined in a separate JavaScript file. However, it is declared globally and works in reality.

How do I write a jasmine test for this clear_canvas function?

JavaScript Canvas_Actions:

(function() {
  window.Canvas_Actions = (function() {
    function Canvas_Actions() {}
    Canvas_Actions.prototype.clear_canvas = function() {
      moving_canvas_context.clearRect(0, 0, moving_canvas.width, moving_canvas.height);
      main_canvas_context.drawImage(window.background_image, 0, 0, main_canvas.width, main_canvas.height);
      return window.canvas_objects = [];
    };
    return Canvas_Actions;
  })();
}).call(this);

Jasmine Test for Canvas_Actions:

(function() {
  describe('Canvas Actions', function() {
    return describe('clear_canvas', function() {
      return it('clears the canvases and deletes all objects', function() {
        var actions;
        jasmine.getFixtures().fixturesPath = "../spec/javascript/fixtures";
        loadFixtures("canvas_fixture.html");
        actions = new Canvas_Actions();
        actions.clear_canvas();
        return expect(canvas_objects).toEqual([]);
      });
    });
  });
}).call(this);
Share Improve this question edited Jun 26, 2019 at 10:09 serv-inc 38.2k9 gold badges189 silver badges206 bronze badges asked Nov 18, 2011 at 1:36 JohnJohn 4,3725 gold badges34 silver badges50 bronze badges
Add a comment  | 

3 Answers 3

Reset to default 11

it is declared globally and works in reality

Well, it also needs to be declared when the test runs. So you're probably missing a reference to the script where it is defined in the testing fixture html.

Also, global variables are normally not a good idea, they tend to create difficult bugs. Since you're already using jasmine as a testing framework, try to abstract the dependency on that global variable in something that you pass to your code under test. Then, use jasmine's mocking abilities to test it.

If you remove the global references from Canvas_Actions, it could look like this:

var Canvas_Actions = function(canvas) { 
  this.canvas = canvas; 
}
Canvas_Actions.prototype.clear_canvas = function(background_image) {
  var canvas = this.canvas;
  canvas.getContext().clearRect(0, 0, canvas.width, canvas.height);
  canvas.getContext().drawImage(background_image, 0, 0, canvas.width, canvas.height);
  canvas.clearObjects();
};

You can mock the canvas argument with jasmine and test Canvas_Actions in isolation.

As can be noted, this code might unearth a Canvas class, and you might find out that clear_canvas belongs in there. Use the tests to guide your design, one step at a time.

Jordão is absolutely right, however there's an ugly option too.
Attach your global object to the window in beforeEach method. Code below probably does not work (haven't tested it), but should be good enough to understand how to work around this jasmine global object problem.

(function() {
  describe('Canvas Actions', function() {
    beforeEach(function () {
        window.Canvas_Actions = (function() {
function Canvas_Actions() {}
Canvas_Actions.prototype.clear_canvas = function() {
  moving_canvas_context.clearRect(0, 0, moving_canvas.width, moving_canvas.height);
  main_canvas_context.drawImage(window.background_image, 0, 0, main_canvas.width, main_canvas.height);
  return window.canvas_objects = [];
};
return Canvas_Actions;
})();
    });
return describe('clear_canvas', function() {

  return it('clears the canvases and deletes all objects', function() {
    var actions;
    jasmine.getFixtures().fixturesPath = "../spec/javascript/fixtures";
    loadFixtures("canvas_fixture.html");
    actions = window.Canvas_Actions;
    actions.clear_canvas();
    return expect(canvas_objects).toEqual([]);
  });
});
  });
}).call(this);

EDIT: as per comments by @John Henckel and @serv-inc apparently there might be an error (ReferenceError: window is not defined) to fix it instead of window use global like: window.Canvas_Actions change to global.Canvas_Actions

It seems like JasmineJS uses the global property. So @Jordão's answer nonwithstanding, you could replace

window.Canvas_Actions = (function() {

with

global.Canvas_Actions = (function() {

本文标签: