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 method not found in before(:all) block #92

Closed
wjdix opened this issue Dec 16, 2011 · 12 comments
Closed

stub method not found in before(:all) block #92

wjdix opened this issue Dec 16, 2011 · 12 comments

Comments

@wjdix
Copy link

wjdix commented Dec 16, 2011

Migrating from Rais 2.3 to Rails 3 and Rspec 1 to Rspec 2. Previously passing test with stub in before(:all) block now fails. I added the scenario below to the rspec-mock feature suite and it fails.

  Scenario: stub in a before(:all) block
    Given a file named "example_spec.rb" with:
    """
      class Foo ; end
      describe "a stub in a before(:all) block" do
        before(:all) do
          Foo.stub(:find)
        end
        it "return nil" do
          Foo.find.should be(nil)
        end
      end
    """
    When I run `rspec example_spec.rb`
    Then the examples should all pass
(::) failed steps (::)

expected "F\n\nFailures:\n\n  1) a stub in a before(:all) block return nil\n     Failure/Error: Foo.stub(:find)\n     NoMethodError:\n       undefined method `stub' for Foo:Class\n     # ./example_spec.rb:4\n\nFinished in 0.00029 seconds\n1 example, 1 failure\n\nFailed examples:\n\nrspec ./example_spec.rb:6 # a stub in a before(:all) block return nil\n" to include "0 failures" (RSpec::Expectations::ExpectationNotMetError)
features/method_stubs/simple_return_value.feature:96:in `Then the examples should all pass'
@wjdix
Copy link
Author

wjdix commented Dec 16, 2011

I see now that this issue should probably be reported in rspec-core. It looks like run_before_each in lib/rspec/core/example.rb is the "culprit". I'll move this issue to the appropriate repo.

@wjdix wjdix closed this as completed Dec 16, 2011
@dchelimsky
Copy link
Contributor

I don't see the issue in rspec-core yet, so will respond here for now:

Stubs in before(:all) are not supported. The fact that it worked for you in rspec-1 was an accident (possibly a bug). The reason is that all stubs and mocks get cleared out after each example, so any stub that is set in before(:all) would work in the first example that happens to run in that group, but not for any others.

We've talked about firing off a warning when calling stub or should_receive in a before(:all), but the binding between rspec-core and rspec-mocks combined with the fact that other frameworks would work differently (and some other uglinesses/inconsistencies) led to us not doing that. I'd be happy to entertain a patch that solved that problem, but don't intend to support stubs in before(:all).

@khrvi
Copy link

khrvi commented Feb 21, 2012

Why stubs in before(:all) is not supported...I think it can be useful in some cases...definitely before(:each) will work as well but why we need to stub one thing before each test? Does it so complicated to support stubs in before(:all)? Sorry if I missed something important

@dchelimsky
Copy link
Contributor

@khrvi re-read my previous comment: "the reason is ...."

@arsduo
Copy link

arsduo commented Apr 16, 2012

Makes sense, though I'm curious why you can't just pass in the context in which the stub is activated (suite, all, each) and clear it when the appropriate block is done. The answer that comes to mind is that you run into issues of shared state (if someone unset the stub in an each, it would affect subsequent tests, possibly inconsistently between runs), and it may also not be feasible (can't say without knowing more about the rspec-core/mocks binding issues you alluded to above).

Either way, I'd like to add a few keywords in the hope that Google will index them and save some time for the next person who upgrades (in my case, from 2.8 to 2.9, oddly) and encounters the same error I did.

undefined method `expectation_ordering' for nil:NilClass
/Users/username/.rvm/gems/ruby-1.9.2-p290@project/gems/rspec-mocks-2.9.0/lib/rspec/mocks/proxy.rb:36:in `initialize'
/Users/username/.rvm/gems/ruby-1.9.2-p290@project/gems/rspec-mocks-2.9.0/lib/rspec/mocks/methods.rb:131:in `new'
/Users/username/.rvm/gems/ruby-1.9.2-p290@project/gems/rspec-mocks-2.9.0/lib/rspec/mocks/methods.rb:131:in `__mock_proxy'
/Users/username/.rvm/gems/ruby-1.9.2-p290@project/gems/rspec-mocks-2.9.0/lib/rspec/mocks/methods.rb:35:in `stub'

@dchelimsky
Copy link
Contributor

@arsduo I've thought of doing that (different scopes) but it would become very confusing for end-users because anything that is stubbed in more than one scope would get reset at the end of the smallest scope. e.g.

before(:all) do
  Thing.stub(:find => double('thing'))
end

it "does something in some condition" do
  Thing.stub(:something_else => double('thing'))
  # when this example ends, Thing is reset, removing the stubs of both 'find' and 'something_else'.
end

@mltsy
Copy link

mltsy commented Jul 10, 2012

Would it make sense to create a stub method, available in before(:all), that simply stores a set of stubs to run before(:each) ?

I would think that would have the intended effect - although in that case, we might as well just encourage putting it in before(:each). So, long story short, I guess agree with the idea of just triggering a warning when the stub method is called in before(:all) if that can be made possible. That seems like the right answer.

@dchelimsky
Copy link
Contributor

Would it make sense to create a stub method, available in before(:all), that simply stores a set of stubs to run before(:each)?

Absolutely not! That would become very confusing if we ever decide to support stubs in before(:all) in the future. If anything we could add an implementation that raises an error explaining what is/is not supported.

@martinemde
Copy link
Contributor

The fact that this didn't raise anything but a NoMethodError sent me on hours of chasing through documentation and discussions trying to figure out what's wrong with rspec. I have a suite that really only uses before(:all) since the setup is so very time consuming, so my experience was that the stub method just didn't exist no matter what I did.

Can rspec at least raise when this is used in a context that doesn't support it. I just spent my day on this before I figured out it was the before(:all) context causing it.

@myronmarston
Copy link
Member

@martinemde -- thanks for reminding us about this issue. I agree we should improve this. I've opened #240 to track that work.

@martinemde
Copy link
Contributor

@myronmarston Thank you! That'll help save some others from table to head collisions.

@sekmo
Copy link

sekmo commented Nov 6, 2017

summary for 2017 visitors: use allow instead of stub, and use it on single examples or on before(:each) statements.

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

8 participants