I want to stub set_user_tokens which is executed on the initialized (not saved) ActiveRecord object. This method assigns a token to the login object.
class AwareLogin < Authenticatable
def authenticate!
login = Login.find_or_initialize_for_authentication(params[:login][:email], 'aware')
class << login
include AwareAuth
end
if login.valid_password?(password) || (set_token = login.id.nil? && aware_response.success?)
login.set_user_tokens(aware_response) if set_token
success!(login)
else
aware_response.success? ? fail!(:aware_auth) : raise(ActiveRecord::Rollback)
end
end
end
end
So I want to stub setu_user_tokens method:
login.set_user_tokens(aware_response) if set_token
to receive login ActiveRecord object with attributes of oauth_tokens like below:
login.oauth_token
=> {"access_token" => return_token,"refresh_token" => nil,"token_expiration" => 1200 }
I've tried:
allow_any_instance_of(Login).to receive(:set_user_tokens).with(status: 200, body: { access_token: return_token }.to_json, success?: true).and_return(
oauth_tokens: {
"access_token" => return_token,
"refresh_token" => nil,
"token_expiration" => 1200 },
)
But I'm getting an error:
Login does not implement #set_user_tokens
CodePudding user response:
I would be willing to bet your issue is set_user_tokens is part of AwareAuth.
Since you are only including this module in the eigenclass of the instance (login) as part of the AwareLogin#authenticate! method, the Login class does not implement that method at any point in time.
Is there a reason you are doing it this way rather than just including AwareAuth in the Login class in the first place?
Either way, while your question appears to lack context for the test itself, if I understand correctly, we should be able to resolve these issues as follows:
it 'sets user tokens' do
login = Login
.find_or_initialize_for_authentication('[email protected]', 'aware')
.tap {|l| l.singleton_class.send(:include, AwareAuth) }
allow(Login).to receive(:find_or_initialize_for_authentication).and_return(login)
allow(login).to receive(:set_user_tokens).and_return(
oauth_tokens: {
"access_token" => return_token,
"refresh_token" => nil,
"token_expiration" => 1200 }
)
#perform your action and expectations here
end
By using partial doubles you can stub the specific methods you need to without impacting any other functionality of the object itself.
