Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

stub_const overwrites Class definition #1079

Closed
tdeo opened this issue Apr 28, 2016 · 4 comments
Closed

stub_const overwrites Class definition #1079

tdeo opened this issue Apr 28, 2016 · 4 comments

Comments

@tdeo
Copy link

tdeo commented Apr 28, 2016

When using stub_const before the Class containing the constant has been loaded, a module is automatically created with the name.

Here is a minimal working example (on Rails file structure):
app/models/model.rb:

class Model
  CONST = 10

  def initialize
    puts 'Creating instance'
  end
end

spec/models/model_spec.rb:

require 'rails_helper'

describe 'something' do
  describe 'stub_const' do
    it 'doesn\'t overwrite the class definition' do
      stub_const('Model::CONST', 2)
      Model.new
    end
  end
end

And that test fails with:

Failures:

  1) something stub_const doesn't overwrite the class definition
     Failure/Error: Model.new
     NoMethodError:
       undefined method `new' for #<Module:0x000000089a8be0>

I think in that case the Module or Class should be loaded and an exception raised in case it doesn't exists or the original constant doesn't (The same way using expect(Class).to receive(:method) fails if method doesn't exist).

I'm using rspec-mocks 3.3.2 with rails 4.2.3 and haven't tried it with the master branch, but nothing appears in the changelog.

@myronmarston
Copy link
Member

When using stub_const before the Class containing the constant has been loaded, a module is automatically created with the name.

This is working by design: since Model does not exist, in order to stub Model::CONST, RSpec has to create Model, but it has no way to know if it should be created as a module or class. It creates it as a module since modules are so often used as namespaces (e.g. MyGemModule::SomeClass).

I agree it's not ideal, but when RSpec is working with limited information (as it is in this case) it's not clear what the "right" thing is.

I think in that case the Module or Class should be loaded

RSpec does not do any autoloading. My rule of thumb is: if I want something loaded, I load it by requiring it. Just add a require 'model' at the top of your spec file. Of, if you are using Rails autoloading, reference the constant before the stub_const method gets executed -- for example, RSpec.describe Model should do the trick.

There was talk at some point about potentially adding some autoloading for this kind of situation in rspec-rails since that's a rails context where autoloading is common, but I don't remember what conclusion we arrived at and I can't find the issue. @JonRowe do you remember?

@JonRowe
Copy link
Member

JonRowe commented Apr 29, 2016

We talked about it but never did anything about it, my suggested work around at the time was to do stub_const("#{Model}::CONST", 2) to trigger the autoloading.

@JonRowe JonRowe closed this as completed Apr 29, 2016
@tdeo
Copy link
Author

tdeo commented Apr 29, 2016

That's exactly the workaround I used as well

tahb added a commit to DFE-Digital/teaching-vacancies that referenced this issue Jul 5, 2018
* I was observing this problem: rspec/rspec-mocks#1079 when running a feature spec in isolation.

```
  1) School viewing public listings when signed in with DfE Sign In A signed in school should see a link back to their own dashboard when viewing public listings
     Failure/Error: validates :minimum_salary, salary: { presence: true, minimum_value: true }

     NoMethodError:

       undefined method `new' for SalaryValidator:Module
```
tahb added a commit to DFE-Digital/teaching-vacancies that referenced this issue Jul 9, 2018
* I was observing this problem: rspec/rspec-mocks#1079 when running a feature spec in isolation.

```
  1) School viewing public listings when signed in with DfE Sign In A signed in school should see a link back to their own dashboard when viewing public listings
     Failure/Error: validates :minimum_salary, salary: { presence: true, minimum_value: true }

     NoMethodError:

       undefined method `new' for SalaryValidator:Module
```
despo pushed a commit to DFE-Digital/teaching-vacancies that referenced this issue Jul 9, 2018
* I was observing this problem: rspec/rspec-mocks#1079 when running a feature spec in isolation.

```
  1) School viewing public listings when signed in with DfE Sign In A signed in school should see a link back to their own dashboard when viewing public listings
     Failure/Error: validates :minimum_salary, salary: { presence: true, minimum_value: true }

     NoMethodError:

       undefined method `new' for SalaryValidator:Module
```
@keogh
Copy link

keogh commented Jul 25, 2019

thanks for the workaround, more than 3 years after @JonRowe post, it still works! 🤔

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants