Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jasmine specs generating different random numbers than on execution

I have a Jasmine test that is failing because a random number is being generated and this random value is different for execution and spec.

fetch: function(options) {
    if(typeof options === "undefined") {
        options = {};
    }
    if(typeof options.data === "undefined") {
        options.data = {};
    }
    options.data.id = this.journalId;
    options.data.random = Math.floor(Math.random()*10000);
    col.prototype.fetch.call(this, options);
}

The test below fails because Math.floor(Math.random()*10000) is generating different values.

it("should call parent fetch with default options", function() {
  this.collection.fetch();
  expect(this.fetchSpy).toHaveBeenCalledWith({
    data: {
      id: 1,
      random: Math.floor(Math.random()*10000) 
    }
  }); 
});

Is there a way to make my test pass for cases where I have random numbers being generated?

like image 588
Huy Avatar asked Apr 01 '13 22:04

Huy


People also ask

Should unit tests have randomness?

Randomization is useful, but there are times when you should use constant data: Using randomization in your unit tests is appropriate in most situations, but not in all situations. There will be very specific times when you should use constant data to make sure every base is covered. Then, by all means, do so.

How can we make individual specs pending in Jasmine?

Aditionally, there is a pending() function you can call anywhere inside a spec to mark it as pending: it("can be declared by calling 'pending' in the spec body", function() { expect(true). toBe(false); pending(); }); See also the documentation on pending specs in Jasmine 2.0.

Which Jasmine function helps to groups a number of the related tests?

Jasmine provides the describe global function to define group-related specs. The string parameter of the describe function is used to name the collection of specs, which represents a specific feature or component.


2 Answers

You're able to mock Math.random function. Jasmine 2:

it("should call parent fetch with default options", function() {
  spyOn(Math, 'random').and.returnValue(0.1);
  this.collection.fetch();
  expect(this.fetchSpy).toHaveBeenCalledWith({
    data: {
      id: 1,
      random: Math.floor(Math.random()*10000)
    }
  }); 
});

Jasmine 1:

it("should call parent fetch with default options", function() {
  jasmine.spyOn(Math, 'random').andReturn(0.1);
  this.collection.fetch();
  expect(this.fetchSpy).toHaveBeenCalledWith({
    data: {
      id: 1,
      random: Math.floor(Math.random()*10000)
    }
  }); 
});
like image 165
ValeriiVasin Avatar answered Oct 19 '22 23:10

ValeriiVasin


You SHOULD NOT spyOn Math.random.

There are many package using this function (even Jasmine), the better way will be writing a method to wrap the random stuff.

class Fetcher {
  fetch(url) {
    const rand = this.generateRandomNumber(64);
    // ...
  }

  generateRandomNumber(n) {
    return Math.floor(Math.random() * n);
  }
}

Now you can mock it!

it('should pass', () => {
  const fetcher = new Fetcher();
  // mock
  spyOn(fetcher, 'generateRandomNumber').and.returnValues(1,2,3);

  // action
  const result = fetcher.fetch('some-url');

  // assertion
  expect(result).toBe('some-result');
});
like image 21
呂學洲 Avatar answered Oct 19 '22 23:10

呂學洲