Reputation: 77
I'm trying to test a very simple method that takes in 2 numbers and uses them to work out a percentage. However, when I try and run the tests it fails with the following error:
NoMethodError: undefined method `pct' for Scorable:Module
./spec/models/concerns/scorable_spec.rb:328:in `block (2 levels) in
<top (required)>'
./spec/rails_helper.rb:97:in `block (3 levels) in <top (required)>'
./spec/rails_helper.rb:96:in `block (2 levels) in <top (required)>'
-e:1:in `<main>'
Here's my spec file for the module:
require 'rails_helper'
RSpec.describe Scorable, :type => :concern do
it "pct should return 0 if den is 0 or nil" do
expect(Scorable.pct(nil, 15)).to eq(0)
expect(Scorable.pct(0, 15)).to eq(0)
end
end
Here is the pct method located in Scorable.rb:
def pct(num,den)
return 0 if num == 0 or num.nil?
return (100.0 * num / den).round
end
And here's my rspec_helper:
if ENV['ENABLE_COVERAGE']
require 'simplecov'
SimpleCov.start do
add_filter "/spec/"
add_filter "/config/"
add_filter '/vendor/'
add_group 'Controllers', 'app/controllers'
add_group 'Models', 'app/models'
add_group 'Helpers', 'app/helpers'
add_group 'Mailers', 'app/mailers'
add_group 'Views', 'app/views'
end
end
RSpec.configure do |config|
config.expect_with :rspec do |expectations|
expectations.include_chain_clauses_in_custom_matcher_descriptions =
true
end
config.raise_errors_for_deprecations!
config.mock_with :rspec do |mocks|
mocks.verify_partial_doubles = true
end
end
I'm very new to RSpec and have been puzzling over this one for more than a day. It's definitely pointing to an existing method, as when I use Go To Declaration in RubyMine it opens the method declaration. Can anyone maybe shed some light for me on this one? I'm sure I'm overlooking something incredibly simple.
Upvotes: 0
Views: 8247
Reputation: 121010
To make the module method callable with Module.method
notation is should be declared in module scope.
module Scorable
def self.pct(num,den)
return 0 if num == 0 or num.nil?
return (100.0 * num / den).round
end
end
or:
module Scorable
class << self
def pct(num,den)
return 0 if num == 0 or num.nil?
return (100.0 * num / den).round
end
end
end
or with Module#module_function
:
module Scorable
module_function
def pct(num,den)
return 0 if num == 0 or num.nil?
return (100.0 * num / den).round
end
end
Note, that the latter declares both module method and normal instance method within this module.
Sidenote: using return
in the very last line of the method is considered a code smell and should be avoided:
module Scorable
def self.pct(num,den)
return 0 if num == 0 or num.nil?
(100.0 * num / den).round
end
end
Upvotes: 2