简体   繁体   中英

How should I avoid stubbing properties with Sinon.js

I've discovered that Sinon doesn't let you stub properties, only methods. I'm trying to figure out how to deal with/embrace this.

I have the following code:

var Player = {
  addPoints: function(points) {
    this.score += points;
  },
  score: 0
}

var Game = {
  setPlayers: function(players) {
    this.players = players;
  },
  over: function() {
    return this.players.some(function(player) {
      return player.score >= 100;
    });
  },
}

Here's a test I wrote:

describe("Game", function() {
  it("is over if a player has at least 100 points", function() {
    var game = Object.create(Game);
    player = Object.create(Player);
    game.setPlayers([player]);
    player.addPoints(100);
    game.over().should.be.true;
  });
});

It feels wrong to me to have to go in and call addPoints() on Player when I'm testing Game . My initial instinct was to stub Player.points , but I can't do so, because Sinon only stubs properties, not methods.

How should I be thinking about this?

I emailed the SinonJS mailing list, and the author wrote back:

Exactly like you have done. Directly writing to the score property completely defeats the purpose of the addPoints method, and makes your test tightly coupled to the implementation (thus making it brittle).

If you really do want to "stub" the property, here's how:

describe("Game", function() {
  it("is over if a player has at least 100 points", function() { 
    var game = Object.create(Game); 
    player = Object.create(Player); 
    game.setPlayers([player]); 
    player.score = 100; 
    game.over().should.be.true;
  });
});

It's a property on an instance - no point in being too clever about it. I still recommend you don't do it this way though.

You don't have to stub game.points just set it. So you can create a simple mock for Game , which is just an object holding a spy for the setPlayer method. and then you can set score in the test to what ever you want.

describe("Game", function() {
  var game;

  before(function(){
    game = {addPoints: jasmine.createSpy()}
  })

  it("is over if a player has at least 100 points", function() { 
    game.score = 100;
    player = Object.create(Player);
    game.setPlayers([player]);
    game.over().should.be.true;
  });
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM