Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing a Class inside of a Module with RSpec

So, I have a module in my ruby code which looks something like this:

module MathStuff
  class Integer
    def least_factor
      # implementation code
    end
  end
end

and I have some RSpec tests in which I would like to test that my Integer#least_factor method works as expected. we'll say that the tests are in the same file for simplicity. The tests look something like this:

describe MathStuff do
  describe '#least_factor' do
    it 'returns the least prime factor' do
      expect(50.least_factor).to eq 2
    end
  end
end

Unfortunately, when I run the tests, I get an error like this:

NoMethodError:
    undefined method `least_factor' for 50:Fixnum

Please let me know if you know how to include the MathStuff::Integer class for testing.

Note: just for clarification, I am actually trying to open up the Ruby Integer class here and add methods to it.

like image 525
Will Piers Avatar asked Oct 06 '13 04:10

Will Piers


2 Answers

Your code should look like:

describe MathStuff::Integer do
  describe '#least_factor' do
    it 'returns the least prime factor' do
      expect(MathStuff::Integer.new.least_factor).to eq 2
    end
  end
end

But you're calling 50.least_factor and 50 is a Fixnum object, not your MathStuff::Integer and it doesn't have that method defined.

like image 101
Maurício Linhares Avatar answered Oct 05 '22 23:10

Maurício Linhares


Before the addition of refinements in Ruby 2.1 (and experimental support in 2.0), you couldn't limit the scope of a monkeypatch like this to a particular context (i.e. a module).

But the reason your example doesn't work is that defining an Integer class under the Mathstuff module creates a new class which has nothing to do with the Integer core class. The only way to override the core class is to open the class at the top level (not within a module).

I usually put core extensions in a lib/core_ext subdirectory, named after the class they are patching, in your case lib/core_ext/integer.rb.

like image 42
rickyrickyrice Avatar answered Oct 05 '22 22:10

rickyrickyrice