Ruby-on-rails – Adding rspec test for library module doesn’t seem to pickup Expectations and Matchers

rspecruby-on-railstesting

I'm adding more rspec testing to my app and would like to test a ScoringMethods module, which is in /lib/scoring_methods.rb. So I added a /spec/lib directory and added scoring_methods_spec.rb there. I required spec_helper and set up the describe block as so:

require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')

describe ScoringMethods do

  describe "should have scorePublicContest method" do
    methods = ScoringMethods.instance_methods
    methods[0].should match(/scorePublicContest/)
  end
end

Now methods[0] is a String and there is no problem matching the public method name with the regular expression. And the relative path to "spec_helper" is correct.

The problem is that the entire setup doesn't seem to use the rspec library.
Running the example yields:

  ./spec/lib/scoring_methods_spec.rb:7: undefined method `match' for Spec::Rails::Example::RailsExampleGroup::Subclass_1::Subclass_1:Class (NoMethodError)
     ...

The entire Expectation and Matcher support seems to be missing. To test my supposition, I changed a working helper spec by replacing "is_instance_of" to "is_foobar_of". That test simply fails and says "is_foobar_of" is not a method of the targeted object; that it, this entire Spec::Rails::Example… hierarchy isn't present.

I've tried using other matchers as well. I've tried "be_instance_of" and some others. It seems that I'm not including the rspec library properly.

Finally, ScoringMethods is a module, just the same way Helpers are modules. So I thought that it would be possible to test a module (as opposed to classes, such as Controllers and Models).

I'd greatly appreciate your thoughts on what I've done wrong. Perhaps there is a more effective way of testing library modules? Thanks!

Best Solution

You should include your test block in an "it" block. For example:

require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')

describe ScoringMethods do

  describe "should have scorePublicContest method" do
    it "should have a scorePublicContest method" do
      methods = ScoringMethods.instance_methods
      methods[0].should match(/scorePublicContest/)
    end
  end
end

You will find that the methods names returned aren't guaranteed to be in the order they exist in the file.

A model we often use when testing Modules is to include the module in either a class created for the test (inside the spec file) or included inside the spec itself.

Related Question