ArgumentError only within rspec test

716 views
Skip to first unread message

Jonas Osborn

unread,
Jul 24, 2016, 2:36:23 PM7/24/16
to rspec
Hi
I am very new to ruby and rspec so apologies if this is a stupid question, but I'm trying to start using rspec and am getting an error that is confusing me. I have a spec that fails on an ArgumentError, the confusing thing for me is running the same thing in a interactive ruby shell or my script doesn't give an ArgumentError. So while I would normally think this was a problem with the gem I am using or how I am using it, the fact that I was having no problems until I tried to use rspec is making me wonder if I have missed something about rspec. Anyway here is my spec file:
require "cinch"

describe "Cinchbot" do
  it "why does this not work" do

     Failure/Error: Cinch::Bot.new

     ArgumentError:
       wrong number of arguments (2 for 0)
     # /usr/local/rvm/gems/ruby-2.2.4/gems/cinch-2.3.2/lib/cinch/bot.rb:354:in `initialize'
     # /usr/local/rvm/gems/ruby-2.2.4/gems/cinch-2.3.2/lib/cinch/bot.rb:354:in `initialize'
     # ./spec/bot/bot_spec.rb:5:in `new'
     # ./spec/bot/bot_spec.rb:5:in `block (2 levels) in <top (required)>'

Myron Marston

unread,
Jul 24, 2016, 2:47:36 PM7/24/16
to rs...@googlegroups.com
Based on your stack trace, the problem appears to originate from this line of code:


Notice that it is calling `super(nil, self)`. It's passing 2 arguments up to the superclass's `initialize` method but the superclass's definition does not accept any arguments, so Ruby is giving you an error, indicating 2 args were passed but 0 are accepted.

That class is subclassing `User` (presumably, `Cinch::User`, given it is defined within the `Cinch` module).  `Cinch::User` accepts a variable number of arguments:


So it's quite strange you're getting the error.  My best guess is that `User` is perhaps being resolved to `::User` (e.g. your application's User class) instead of `Cinch::User`, but that should  only happen if `Cinch::User` is not defined -- and it certainly is being required at the top of `cinch/bot.rb`.

I don't think there's any way RSpec can directly be causing this, but there is probably something different about the environment the code is running in via RSpec vs IRB.  You might be able to figure it out by printing `$LOAD_PATH` and `$LOADED_FEATURES` to see the differences in load path and what files have been loaded in the two environments.

I'd also suggest you check with the maintainers of the cinch library.  Something weird is going on in it.

HTH,
Myron



--
You received this message because you are subscribed to the Google Groups "rspec" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rspec+un...@googlegroups.com.
To post to this group, send email to rs...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/rspec/913967f7-9e85-4087-a393-e2a4d1cf397c%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Jonas Osborn

unread,
Jul 24, 2016, 3:25:30 PM7/24/16
to rspec
Thanks for the response.
Incidentally I did have more to add in my first post but being new to Google group pressed tab and enter accidentally and suddenly it was gone... 
It is as you say, its to do with a conflicting ::User. The trouble is I have a Cinch::User in my code that when I run my application, re-opens the User class and adds some methods. But when I run 'rspec', the Cinch::User class is not re-opened, somehow it overwrites all of Cinch::User (thus the problem with initialize).
I googled around a bit and apparently it is because rspec automatically adds the local lib folder to $LOAD_PATH. So running 'ruby -Ispec -rrspec/autorun path/to/spec.rb' (i.e. omitting the -Ilib flag) encounters no problems.
Is there a way I can either not automatically add lib to $LOAD_PATH when running rspec?
or is running 'rspec' not important and should I just always run the ruby command?
or is there a different way I could re-open Cinch::User without it being overwritten when 'rspec'-ing?
or any other solution?
I could also move my code out of lib but although I am new it is my impression that that is where the code should be.
Cheers,
Jonas

Myron Marston

unread,
Jul 24, 2016, 3:50:31 PM7/24/16
to rs...@googlegroups.com
Ah, I see what's happening.  Because you've defined a file at `lib/cinch/user.rb` and `lib` is on the load path, it means that a `require 'cinch/user'` from anywhere will load your file instead of the file in the gem.

One solution is to remove `lib` from the load path.  RSpec does not expose an API to prevent it from adding `lib`, but you can manually remove it from `$LOAD_PATH` by putting logic in `spec/spec_helper.rb` (or similar) to do that.  `$LOAD_PATH` is a ruby array so you can modify it however you like from anywhere in your program.

That said, I wouldn't recommend that solution.  RSpec puts `lib` on the load path for a reason -- that's the standard environment ruby code usually runs in.  For example, if you have a gem, rubygems will put your `lib` directory on the load path.  I thought that Rails also put `lib` on the load path but I might be wrong about that given I haven't used rails in 5+ years.  Remove `lib` from the load path will solve your immediate problem but I think it papers over the problem and the problem might resurface when you run your code in other environments.

Instead, I recommend you avoid putting any of your logic in files named `lib/cinch/*`.  The `cinch` namespace is owned by the gem and if any of your code defined in a directory named `lib/cinch` is prone to having these sorts of issues.  Instead, I recommend renaming your directory to `lib/cinch_extensions` or `lib/my_app/cinch` or similar.  Then there's no risk of requires not working properly.

HTH,
Myron

Reply all
Reply to author
Forward
0 new messages