Rspec "NoMethodError" from nested module - ruby-on-rails

I'm running into a weird error:
Class:
module AnimalSanctuary
module AnimalInspector
class AnimalPicker
def initialize(number_of_animals, ids)
#number_of_animals = number_of_animals
#ids = ids
end
...
def pick_animals(animal)
end
end
end
test:
require 'rails_helper'
RSpec.describe AnimalSanctuary::AnimalInspector::AnimalPicker do
describe ".pick_animals" do
context "pick an available animal" do
it "returns animal name" do
expect(AnimalSanctuary::AnimalInspector::AnimalPicker.pick_animals("Dog")).to eq("Dog")
end
end
end
end
I get the following error:
NoMethodError:
undefined method `pick_animals' for AnimalSanctuary::AnimalInspector::AnimalPicker:Class
Rspec calls the class but not the method which has stumped me. Am I doing something wrong?

The definition of pick_animals is an instance method.
To call it, you will need to instantiate an object of the class using the new method as shown below. I have passed in random values to your initializer (1, [1,2]) however you can set them as you like.:
number_of_animals = 1
ids = [1,2]
AnimalSanctuary::AnimalInspector::AnimalPicker.new(number_of_animals, ids).pick_animals("Dog")
Otherwise, to call it the way you are calling it, you will need to redefine it as a class method by using self.pick_animals as shown below:
module AnimalSanctuary
module AnimalInspector
class AnimalPicker
...
def self.pick_animals(animal)
end
end
end

yeah pick_animals is an instance method.
you can use the following in your rspec
expect_any_instance_of(nimalSanctuary::AnimalInspector::AnimalPicker).to receive(:pick_animals).with("dogs").to_eq("Dog")
Hope this helps

Related

Calling rspec methods from different file

I am trying to write a class in my code to wrap some of the RSpec calls. However, whenever I try to access rspec things, my class simply doesn't see the methods.
I have the following file defined in spec/support/helper.rb
require 'rspec/mocks/standalone'
module A
class Helper
def wrap_expect(dbl, func, args, ret)
expect(dbl).to receive(func).with(args).and_return(ret)
end
end
end
I get a NoMethodError: undefined method 'expect', despite requiring the correct module. Note that if I put calls to rspec functions before the module, everything is found correctly.
I've tried adding the following like to my spec_helper.rb:
config.requires << 'rspec/mocks/standalone'
But to no avail.
I managed to use class variables in my class and passing the functions through from the global context, but that solution seems quite extreme. Also I was able to pass in the test context itself and storing it, but I'd rather not have to do that either.
expect functions by default is associated with only rspec-core methods like it before . If you need to have expect inside a method, you can try adding the Rspec matcher class in the helper file.
include RSpec::Matchers
that error because the self which call expect is not the current rspec context RSpec::ExampleGroups, you could check by log the self
module A
class Helper
def wrap_expect(dbl, func, args, ret)
puts self
expect(dbl).to receive(func).with(args).and_return(ret)
end
end
end
# test case
A::Helper.new.wrap_expect(...) # log self: A::Helper
so obviously, A::Helper does not support expect
now you have 2 options to build a helper: (1) a module or (2) a class which init with the current context of test cases:
(1)
module WrapHelper
def wrap_expect(...)
puts self # RSpec::ExampleGroups::...
expect(...).to receive(...)...
end
end
# test case
RSpec.describe StackOverFlow, type: :model do
include WrapHelper
it "...." do
wrap_expect(...) # call directly
end
end
(2)
class WrapHelper
def initialize(spec)
#spec = spec
end
def wrap_expect(...)
puts #spec # RSpec::ExampleGroups::...
#spec.expect(...).to #spec.receive(...)...
end
end
# test case
RSpec.describe StackOverFlow, type: :model do
let!(:helper) {WrapHelper.new(self)}
it "...." do
helper.wrap_expect(...)
end
end

RSpec: How to properly test class method that loops through a collection / calls instance method

Consider the following class and class method:
class Foo < ActiveRecord::Base
scope :active, -> { where(deleted: false) }
class << self
def some_class_method
active.each do |foo|
foo.some_instance_method
end
end
end
end
what is the best practice to test such a method in RSpec? What I have learned thus far suggests that I should make sure that each active instance of Foo receives a call to some_instance_method, but if I were to make an expectation regarding Foo.some_class_method, to my knowledge I cannot assert a nested expectation about any instance of Foo.
Any help would be appreciated!!
The approach I would take is to separately test some_instance_method, like:
it 'should return some value' do
expect(foo.some_instance_method).to eq('some value')
end
You could then run the class method and test that the transformations happened as expected:
context 'Foo#some_class_method' do
it 'should have some effect' do
expect(some_comparison_variable).to eq('some_before_state')
Foo.some_class_method
expect(some_comparison_variable).to eq('some_after_state')
end
end

Testing instantiation of an object in a controller_spec, then calling a method on the resulting object fails

I've get a controller spec that looks like this
describe ExportController do
describe 'GET index' do
target_params = {type:'a', filter: 'b'}
expect(DataFetcher).to receive(:new).with(target_params)
get :index
end
end
The controller looks something like this
class ExportController < ApplicationController
def index
#fetcher = DataFetched.new(target_params)
...
end
end
If I run the spec like this everything is cool. I however want to do something with the resulting DataFetcher object
class ExportController < ApplicationController
def index
#fetcher = DataFetcher.new(target_params)
#list = #fetcher.fetch_list
...
end
end
Now when I run the spec it fails with a no method error
NoMethodError
undefined method 'fetch_list' for nil:NilClass
Whats up with that? The thing is that when I hit this controller through my actual app it works as expected. What is rspec doing behind the scenes here and how would I go about setting this up correctly?
Thanks y'all
Your expect statement is causing nil to be returned from the new, which doesn't have the fetch_list defined. If you want that line to succeed, you'll need to return something that implements the fetch_list method, as in the following:
expect(DataFetcher).to receive(:new).with(target_params)
.and_return(instance_double(DataFetcher, fetch_list: [])
Or you can add this at the end: .and_call_original which imho is way cleaner
expect(DataFetcher).to receive(:new).with(target_params)
.and_call_original

Rspec - Module inside class

I have tried several way to rspec the 'to_type' function. The fact that it is inside the class means that only the class should be able to call it right? I've tried to include the Class in my rspec but the module "Format" is still not recognized. Any ideas how I can rspec this method 'to_type' from the module?
class Loom::Lma < Loom::Base
module Format
STANDARD_FORMATS = {
1 => '0',
2 => '13.4',
}
def to_type(format)
# type is calculated here then return type
# for instance
return :date
end
module_function :to_type
end
def initialize()
#init stuff
end
def otherstuff()
#another function
end
end
RSPEC
it 'type should not be :date' do
include Loom::Lma
Format.to_type('some string format').should_not eq(:date)
end
Any ideas?
Are you sure you want to put that module into a class not the other way around?
Anyway, you can access to_type like this:
Loom::Lma::Format.to_type()

Ruby returns TypeError when trying to require a module

I have a table called Courses with two columns dept_code and course_code that are both strings.
I am writing my specs and I want to call the following module so I can use the valid_course_attributes method to assign attributes to #course.
module CoursesSpecHelper
def valid_course_attributes
{
:dept_code => 'HIST',
:course_code => '1010'
}
end
end
The module is called as such:
describe Courses do
require CoursesSpecHelper
before(:each) do
#course = Courses.new
end
it "should require dept_code" do
#course.attributes = valid_course_attributes.except(:dept_code)
#course.should have(1).error_on(:dept_code)
end
end
When I run my examples, I keep getting the following error:
TypeError: can't convert Module into String
I have tried a couple of variations, but I cannot figure out what this problem means.
Thanks so much!
I think you want
include CoursesSpecHelper

Resources