0

I am currently building a Rock, Paper, Scissors game in Javascript and using TDD to guide my code. I am trying to run a Jasmine test that forces one of my functions to return a set value. I want my "compChoice" function to return a random element from the 'choices' array ["Rock", "Paper", "Scissors"] and in my test want to set this to 'Rock'. My tests are below.

describe("Game", function() {

var game;

beforeEach(function(){
game = new Game();
});

describe('user choice', function(){

it('should equal the choice the user selected', function(){
  game.userSelect("Rock");
  expect(game.userChoice).toEqual("Rock")
});
})

describe('draw', function(){

it('should equal true if user choice and comp choice are the same', function()       {
  game.userSelect("Rock");
  spyOn(game,'compChoice').and.returnValue("Rock");
  expect(game.opponentChoice).toEqual("Rock")
  // expect(game.draw).toEqual(true);
});
})

});

I can tell there's something wrong with my spyOn as my test comes back with "Expected ' ' to equal 'Rock'."

I don't know why it's not calling the spy and setting the value to "Rock" like I asked.

My actual code is down below for reference:

function Game() {
this.choices = ["Rock","Paper","Scissors"];
this.userChoice = "";
this.opponentChoice = "";
}

Game.prototype.userSelect = function(choice){
this.userChoice = choice;
}

Game.prototype.compChoice = function(){
this.opponentChoice =    this.choices[Math.floor(Math.random()*this.choices.length)];
return this.opponentChoice;
 }
Adrian Booth
  • 49
  • 1
  • 4

1 Answers1

0

It looks like you haven't invoked spied method. You define in spy what should happen when function is invoked so in your case

spyOn(game,'compChoice').and.returnValue("Rock");

You have defined, that function compChoice from game object should be spied and when it is invoked that it should return "Rock" value. In next line you do expect

 expect(game.opponentChoice).toEqual("Rock")

So you check here if object attribute opponentChoice is set to "Rock" But you miss to invoke method compChoice, which should set value of opponentChoice. You should paste this

game.compChoice();

between spyOn and expect in your code.

EDITED:

Ok, now I see what's going on. Spy is creating a mock for compChoice method. But it is only a mock and you defined that this mock should return "Rock" value. But actually this mocked function doesn't work like normal compChoice method. So it does not assign opponentChoice value to game object. It only returns "Rock" value as you defined.

It also looks little strange, because it's not unit test. It's more like integration test. You are trying to test how this methods work together. So I think Jasmine doesn't fit for this kind of tests. However if you really would like to test this behaviour you can use callFake method in the following way:

spyOn(game,'compChoice').and.callFake(function(){

              game.opponentChoice = "Rock";
              return "Rock";
});

In this way you are calling fake function which assign also opponenChoice value.

Artur Skrzydło
  • 1,135
  • 18
  • 37
  • was this answer helpful for you ? – Artur Skrzydło Dec 30 '15 at 11:47
  • Sorry for the lack of response Artur and thank you for your answer! I've been away so unable to respond. I attempted what you recommended and invoked the compChoice() function after the Spy and it hasn't worked. When I console.log(game.opponentChoice) it doesn't return anything, when I would have expected Rock to be returned because of the SpyOn. – Adrian Booth Jan 05 '16 at 16:58
  • i edited my previous answer with explanation, why it doesn't work – Artur Skrzydło Jan 07 '16 at 08:53