Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save Sam-Serpoosh/3132125 to your computer and use it in GitHub Desktop.
Save Sam-Serpoosh/3132125 to your computer and use it in GitHub Desktop.
a simple sign_in & sign_out machinery for an app I'm currently working on. I try to follow good OO design & separation of concerns, etc. & extract domain objects as much as possible & have fast-isolated tests. But can't stub simple methods of a module in
module SessionsHelper
include SignInOut
def create_cookie(user_id, user_salt); end
def remember_token; end
def delete_cookie; end
end
describe "Sign in and out" do
include SessionsHelper
it "signs the user in" do
user = stub(:id => stub)
user.stub(:salt => stub)
sign_in(user)
signed_in?.should be_true
end
...
#but as you can see this is so fragile and whenever I have a new method in SessionsHelper I have to define a stub one in the SessionsHelper in the spec
#also I can't express the expectations on its methods and stub some results for better live documentation style of specs and expressing stuff explicitly
#in my specs
end
#This module will be included in SessionsHelper where cookies and remember_token stuff exists
module SignInOut
def sign_in(user)
create_cookie(user.id, user.salt)
@current_user = user
end
def current_user
@current_user || user_from_remember_token
end
def signed_in?
!@current_user.nil?
end
def sign_out
delete_cookie
@current_user = nil
end
def user_from_remember_token
AuthenticateUser.authenticate_with_salt(*remember_token)
end
end
module SessionsHelper
include SignInOut
def create_cookie(user_id, user_salt)
cookies.permanent.signed[:remember_token] = [user_id, user_salt]
end
def remember_token
cookies.signed[:remember_token] || [nil, nil]
end
def delete_cookie
cookies.delete(:remember_token)
end
end
module SessionsHelper
include SignInOut #because it assumed cookies related methods will be in SessionsHelper it should be included in this for simulating the production code
end
describe "Sign in and out" do
include SessionsHelper
#I want to be able to stub some methods in SessionsHelper (or any module like this scenario) and express some call expectations like the following
it "creates the cookie and signs the user in" do
user = stub(:id => 1)
user.stub(:salt => "salt")
SessionsHelper.stub(:create_cookies).with(1, "salt")
sign_in(user)
signed_in?.should be_true
end
#And doing this kind of stubbing on the SessinosHelper methods like delete_cookie, remember_token, etc. (or methods of any other module like this scenario)
end
@Sam-Serpoosh
Copy link
Author

Only self methods in a module can be stubbed out this way (like the last file spec example) but I need to stub out simple methods of a module like the create_cookie for instance in the SessionsHelper and I don't know how to do it!

@steveklabnik
Copy link

Ouch, that double include is crazy :/

@Sam-Serpoosh
Copy link
Author

@steveklabnik I know it's not a good idea doing this. I finally figured it out how to do this. I can do something like the following for better and cleaner testing for this:
describe "Sign in and out" do
let(:sessions_helper) { stub.extend(SignInOut) }

it "creates cookie for the user" do
user_id, user_salt = 1, "salt"
user = stub(:id => user_id, :salt => user_salt)
sessions_helper.should_receive(:create_cookie).with(user_id, user_salt)
sessions_helper.sign_in(user)
end

....
end

this is a better and less confusing way. Thanks to @garybernhardt for the hint.
Thank you Steve for the review, I appreciate that ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment