Luke Schoen Luke Schoen - 1 month ago 8
Ruby Question

Unable to call Ruby mixin instance method from RSpec

Objective:



I want to run a basic RSpec unit test on an instance method of a mixin (module) named Debug. Below are the file contents of the Debug mixin:

Mixin File: ./mixins/debug.rb



module Debug
public
def class_info?
"#{self.class.name}"
end
end


Validate Debug mixin instance methods accessible from RSpec:



When I run
irb
and include the Debug mixin with commands
require_relative './mixins/debug.rb'
and
include Debug
, and then call
Debug.class_info?
it successfully returns
"Module"


Then if I run
rspec
with the following RSpec unit test to confirm that the RSpec context can access the instance methods of the mixin, the test successfully passes:

RSpec Unit Test Setup #1: ./spec/mixins/debug_spec.rb



require_relative '../../mixins/debug.rb'

RSpec.describe Debug, "#class_info?" do
include Debug

before(:each) do
@class_info_instance_method = Debug.instance_methods[0].to_s
end

context "with mixins" do
it "has class info instance method" do
expect(@class_info_instance_method).to eq "class_info?"
end
end
end


Problem when calling Debug mixin instance method from RSpec:



Lastly, I change the RSpec unit test to be as follows, so instead it actually calls the
class_info?
instance method of the Debug mixin:

RSpec Unit Test Setup #2: ./spec/mixins/debug_spec.rb



require_relative '../../mixins/debug.rb'

RSpec.describe Debug, "#class_info?" do
include Debug

before(:each) do
@class_info = Debug.class_info?
end

context "with mixins" do
it "shows class info" do
expect(@class_info).to eq "Module"
end
end
end


But now when I run
rspec
from the command line, why does it return the following error?
(Note: even though in the previous RSpec Unit Test Setup #1 that was entirely similar I checked I could successfully access this Debug mixin instance method)

1) Debug#class_info? with mixins shows class info
Failure/Error: @class_info = Debug.class_info?

NoMethodError:
undefined method `class_info?' for Debug:Module


Note: I have shared the above code in my RubyTest GitHub repo.

Setup and References:



My System:




  • Ruby: ruby 2.3.0p0 (
    ruby -v
    )

  • RSpec: 3.5.4 (
    rspec -v
    )



References:




  • Applying example from Mixins chapter of Programming Ruby book


Answer

When you include a module, the methods become instance methods in the included class. Debug.class_info? doesn't work because there is no class method class_info?. I'm also not sure that the way you've included the module in your test is the best way to do it. Would something like this work?

require_relative '../../mixins/debug.rb'

class TestClass
  include Debug
end

RSpec.describe Debug, "#class_info?" do

  let(:test_instance) { TestClass.new }

  context "with mixins" do
    it "shows class info" do
      expect(test_class.class_info).to eq "TestClass"
    end
  end

end