I'm having a bit of a weird stubbing problem with Rspec. I have two classes that are functionally similar, that both include a module:
class Transaction
module Overview
...
end
end
class Actual
class Overview
include Transaction::Overview
end
end
class Adjustment
class Overview
include Transaction::Overview
end
end
I’m using them both in a method and attempting to stub them in a test like this:
actual_quarters = Actual::Overview::AllQuarters.new(actuals)
actual_overview = double("Actual::Overview", all_quarters: actual_quarters, value_for_report_quarter: 0)
expect(Actual::Overview).to receive(:new).with(activity_presenter, report_presenter).at_least(:once).and_return(actual_overview)
adjustment_quarters = Adjustment::Overview::AllQuarters.new(adjustments)
adjustment_overview = double("Adjustment::Overview", all_quarters: adjustment_quarters, value_for_report_quarter: 0)
expect(Adjustment::Overview).to receive(:new).with(activity_presenter, report_presenter).at_least(:once).and_return(adjustment_overview)
However, running the test gives me the error:
1) Report::Export Report::Export::Row includes the actuals for the previous quarters
Failure/Error: expect(Adjustment::Overview).to receive(:new).with(activity_presenter, report_presenter).at_least(:once).and_return(adjustment_overview)
Transaction::Overview does not implement: new
If I reverse the order of the stubs like so:
adjustment_quarters = Adjustment::Overview::AllQuarters.new(adjustments)
adjustment_overview = double("Adjustment::Overview", all_quarters: adjustment_quarters, value_for_report_quarter: 0)
expect(Adjustment::Overview).to receive(:new).with(activity_presenter, report_presenter).at_least(:once).and_return(adjustment_overview)
actual_quarters = Actual::Overview::AllQuarters.new(actuals)
actual_overview = double("Actual::Overview", all_quarters: actual_quarters, value_for_report_quarter: 0)
expect(Actual::Overview).to receive(:new).with(activity_presenter, report_presenter).at_least(:once).and_return(actual_overview)
I get this error:
1) Report::Export Report::Export::Row includes the actuals for the previous quarters
Failure/Error: expect(Actual::Overview).to receive(:new).with(activity_presenter, report_presenter).at_least(:once).and_return(actual_overview)
Transaction::Overview does not implement: new
Which suggests that Rspec doesn’t like me stubbing classes that include the same module in the same test. Is there any way round this, or something I’m doing wrong?
Try using an instance_double instead. Without having seen your code and the test setup, try changing your test code to:
# is this the class you are testing? if so, use described_class.new(actuals) instead
actual_quarters = Actual::Overview::AllQuarters.new(actuals)
actual_overview_double = instance_double(Actual::Overview, all_quarters: actual_quarters)
# I don't think this should be at_least(:once) - if it is being instantiated more than once, you may need another instance_double
expect(Actual::Overview).to receive(:new).with(activity_presenter, report_presenter).and_return(actual_overview_double)
# again - should this be described_class?
adjustment_quarters = Adjustment::Overview::AllQuarters.new(adjustments)
adjustment_overview_double = instance_double(Adjustment::Overview, all_quarters: adjustment_quarters, value_for_report_quarter: 0)
# again about the at_least(:once)
expect(Adjustment::Overview).to receive(:new).with(activity_presenter, report_presenter).and_return(adjustment_overview)