Rspec-core: Error "wrong number of arguments" when using "subject(:initialize)"

Created on 2 Mar 2017  路  3Comments  路  Source: rspec/rspec-core

Hi, I think this issue is simular to this https://github.com/rspec/rspec-core/issues/1163

When using subject(:initialize), rspec-core raises an error ArgumentError: wrong number of arguments (1 for 0)

I used this spec to simulate it:

require 'rspec'

class LalaPopo
  attr_reader :lala

  def initialize
    @lala = 1
  end
end

describe LalaPopo do
  describe '.initialize_it' do
    subject(:initialize) { described_class.new }

    it 'does something' do
      instance = initialize

      expect(instance.lala).to eq 1
    end
  end
end

and run:

$ rspec test_rspec.rb

the error I received:

Failures:

  1) LalaPopo.initialize_it does something
     Got 0 failures and 2 other errors:

     1.1) Failure/Error: define_method(name) { __memoized.fetch_or_store(name) { super(&nil) } }

          ArgumentError:
            wrong number of arguments (1 for 0)
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/memoized_helpers.rb:295:in `block in let'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/example_group.rb:588:in `new'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/example_group.rb:588:in `run'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/example_group.rb:590:in `block in run'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/example_group.rb:590:in `map'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/example_group.rb:590:in `run'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/runner.rb:118:in `block (3 levels) in run_specs'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/runner.rb:118:in `map'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/runner.rb:118:in `block (2 levels) in run_specs'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/configuration.rb:1875:in `with_suite_hooks'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/runner.rb:113:in `block in run_specs'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/reporter.rb:78:in `report'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/runner.rb:112:in `run_specs'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/runner.rb:87:in `run'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/runner.rb:71:in `run'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/runner.rb:45:in `invoke'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/exe/rspec:4:in `<top (required)>'
          # /home/fabio/.rbenv/versions/2.1.5/bin/rspec:23:in `load'
          # /home/fabio/.rbenv/versions/2.1.5/bin/rspec:23:in `<main>'
          # 
          #   Showing full backtrace because every line was filtered out.
          #   See docs for RSpec::Configuration#backtrace_exclusion_patterns and
          #   RSpec::Configuration#backtrace_inclusion_patterns for more information.

     1.2) Failure/Error: define_method(name) { __memoized.fetch_or_store(name) { super(&nil) } }

          ArgumentError:
            wrong number of arguments (1 for 0)
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/memoized_helpers.rb:295:in `block in let'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/example_group.rb:600:in `new'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/example_group.rb:600:in `run'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/example_group.rb:590:in `block in run'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/example_group.rb:590:in `map'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/example_group.rb:590:in `run'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/runner.rb:118:in `block (3 levels) in run_specs'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/runner.rb:118:in `map'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/runner.rb:118:in `block (2 levels) in run_specs'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/configuration.rb:1875:in `with_suite_hooks'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/runner.rb:113:in `block in run_specs'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/reporter.rb:78:in `report'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/runner.rb:112:in `run_specs'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/runner.rb:87:in `run'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/runner.rb:71:in `run'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/runner.rb:45:in `invoke'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/exe/rspec:4:in `<top (required)>'
          # /home/fabio/.rbenv/versions/2.1.5/bin/rspec:23:in `load'
          # /home/fabio/.rbenv/versions/2.1.5/bin/rspec:23:in `<main>'
          # 
          #   Showing full backtrace because every line was filtered out.
          #   See docs for RSpec::Configuration#backtrace_exclusion_patterns and
          #   RSpec::Configuration#backtrace_inclusion_patterns for more information.

  2) LalaPopo.initialize_it does something
     Got 0 failures and 2 other errors:

     2.1) Failure/Error: define_method(name) { __memoized.fetch_or_store(name) { super(&nil) } }

          ArgumentError:
            wrong number of arguments (1 for 0)
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/memoized_helpers.rb:295:in `block in let'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/example_group.rb:588:in `new'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/example_group.rb:588:in `run'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/example_group.rb:590:in `block in run'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/example_group.rb:590:in `map'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/example_group.rb:590:in `run'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/runner.rb:118:in `block (3 levels) in run_specs'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/runner.rb:118:in `map'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/runner.rb:118:in `block (2 levels) in run_specs'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/configuration.rb:1875:in `with_suite_hooks'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/runner.rb:113:in `block in run_specs'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/reporter.rb:78:in `report'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/runner.rb:112:in `run_specs'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/runner.rb:87:in `run'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/runner.rb:71:in `run'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/runner.rb:45:in `invoke'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/exe/rspec:4:in `<top (required)>'
          # /home/fabio/.rbenv/versions/2.1.5/bin/rspec:23:in `load'
          # /home/fabio/.rbenv/versions/2.1.5/bin/rspec:23:in `<main>'
          # 
          #   Showing full backtrace because every line was filtered out.
          #   See docs for RSpec::Configuration#backtrace_exclusion_patterns and
          #   RSpec::Configuration#backtrace_inclusion_patterns for more information.

     2.2) Failure/Error: define_method(name) { __memoized.fetch_or_store(name) { super(&nil) } }

          ArgumentError:
            wrong number of arguments (1 for 0)
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/memoized_helpers.rb:295:in `block in let'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/example_group.rb:600:in `new'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/example_group.rb:600:in `run'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/example_group.rb:590:in `block in run'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/example_group.rb:590:in `map'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/example_group.rb:590:in `run'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/runner.rb:118:in `block (3 levels) in run_specs'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/runner.rb:118:in `map'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/runner.rb:118:in `block (2 levels) in run_specs'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/configuration.rb:1875:in `with_suite_hooks'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/runner.rb:113:in `block in run_specs'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/reporter.rb:78:in `report'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/runner.rb:112:in `run_specs'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/runner.rb:87:in `run'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/runner.rb:71:in `run'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/lib/rspec/core/runner.rb:45:in `invoke'
          # /home/fabio/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/rspec-core-3.6.0.beta2/exe/rspec:4:in `<top (required)>'
          # /home/fabio/.rbenv/versions/2.1.5/bin/rspec:23:in `load'
          # /home/fabio/.rbenv/versions/2.1.5/bin/rspec:23:in `<main>'
          # 
          #   Showing full backtrace because every line was filtered out.
          #   See docs for RSpec::Configuration#backtrace_exclusion_patterns and
          #   RSpec::Configuration#backtrace_inclusion_patterns for more information.

Finished in 0.0011 seconds (files took 0.11722 seconds to load)
2 examples, 2 failures

Failed examples:

rspec ./test_rspec.rb:15 # LalaPopo.initialize_it does something
rspec ./test_rspec.rb:15 # LalaPopo.initialize_it does something

I know it is weird to create a subject(:initialize), but I found this problem in a legacy system, when I tried to upgrade rspec from 3.0.0 to 3.5.0!

Most helpful comment

Do you think RSpec should detect this before attempting to redefine #initialize?

You mean when a user does let(:initialize), should RSpec warn the user about it? That wouldn't be a bad idea.

All 3 comments

The issue is happening due to the fact that RSpec example groups are classes, and it has to create instances of them--during which Ruby calls the initialize method--in order to run them. In RSpec 3.0.0, RSpec did not define def initialize, and so ExampleGroup.new did not take any arguments, and it did not result in an error. However, your example still did not work properly on RSpec 3.0.0--it's just that it didn't fail loudly. Because your let defines a method, on RSpec 3.0, ExampleGroup.new caused your initialize to get run, meaning it got run eagerly when let is documented as being lazy.

All that's to say: given the special status of initialize in Ruby, I don't think we can support let(:initialize). If you rename it to something else, it'll work.

Do you think RSpec should detect this before attempting to redefine #initialize?

Do you think RSpec should detect this before attempting to redefine #initialize?

You mean when a user does let(:initialize), should RSpec warn the user about it? That wouldn't be a bad idea.

Was this page helpful?
0 / 5 - 0 ratings