How can I test my API created stripe customer properly? - ruby-on-rails

I want to test the API request that creates Stripe customers.
Controller
def create
user = User.create(create_params)
stripe_customer = Stripe::Customer.create({
email: create_params[:email],
name: [create_params[:first_name], create_params[:last_name]].join(' ')
})
user.update(stripe_customer_id: stripe_customer.id)
render(json: { user: user }, status: :ok)
end
private
def create_params
params.permit(
:email,
:first_name,
:last_name
)
end
I saw there is stripe-ruby-mock gem but I am not sure how I can use it?

First of all, you should be able to trust that Stipe's gem will do the right thing when you call it. So, there's no need to test that their create method returns the correct thing. So, all you need to test is that you are calling their API correctly. All you need to do this is an RSpec mock.
Since your code is in a controller, you'll either need to use a controller spec, or you'll need to refactor your code into another class. My preference is the refactor. So, that's what I'll show here.
Controller
Refactored to move business logic into a command class.
def create
user = CreateUser.new(create_params).perform
render(json: { user: user }, status: :ok)
end
CreateUser command class
Refactored a bit to only make one call to the database.
class CreateUser
attr_reader :params
def initialize(params)
#params = params
end
def perform
stripe_customer = Stripe::Customer.create({
email: params[:email],
name: [params[:first_name], params[:last_name]].join(' ')
})
User.create(params.merge(stripe_customer_id: stripe_customer.id))
end
end
Spec file for CreateUser command class
describe CreateUser do
subject(:create_user) { described_class.new(params)
let(:params) do
email: 'some#email.address',
first_name: 'first',
last_name: 'last'
end
describe 'perform' do
let(:stripe_customer_id) { 123 }
before do
allow(Stripe::Customer).to receive(:create).and_return(stripe_customer_id)
allow(User).to receive(:create)
end
it 'creates a Stripe customer' do
create_user.perform
expect(Stripe::Customer).to have_received(:create).with(
email: 'some#email.address',
name: 'first last'
)
end
it 'creates a user with a stripe customer id' do
create_user.perform
expect(User).to have_received(:create).with(
email: 'some#email.address',
first_name: 'first',
last_name: 'last',
stripe_customer_id: 123
)
end
end
end

Related

RSpec controller test - ActionController::UnfilteredParameters: unable to convert unpermitted parameters to hash

In my Rails 6 app I'm trying to test controller methods which allow admin users to update user data without providing user passwords. All actions are run in ActiveAdmin.
admin/users.rb
controller do
def update
model = :user
%w[password password_confirmation].each { |p| params[model].delete(p) } if params[model][:password].blank?
super
end
end
Based on this page I tried to write specs:
admin/users_spec.rb
describe 'PUT update' do
let(:user) { create(:user, :random_email) }
let(:valid_attributes) do
ActionController::Parameters.new(
{
user: {
email: 'michael.kelso#example.com',
password: '',
},
},
)
end
before do
put :update, params: { id: user.id, user: valid_attributes }
end
it 'update user' do
expect(user.reload.email).to eq('michael.kelso#example.com')
end
end
end
What should I do to have this test green?
you can still add strong params for activeadmin.
Using method permit_params method like: permit_params :title, :content, :publisher_id
activeadmin strong param docs:
https://github.com/activeadmin/activeadmin/blob/master/docs/2-resource-customization.md#setting-up-strong-parameters
this post is related to this one: https://github.com/activeadmin/activeadmin/blob/master/docs/2-resource-customization.md#setting-up-strong-parameters

Rspec test not hitting controller update

I am trying to write a simple test to validate updating an Employee and while it works in practice I wanted to write the test anyway.
RSpec.describe EmployeesController, type: :controller do
before(:each) do
admin_user = FactoryBot.create(
:user,
user_type: 1,
email: "admin#admin.com",
password: "oeifhoi2345tf",
password_confirmation: "oeifhoi2345tf"
)
login_as(admin_user)
#employee = create(:employee)
end
it 'expects employee values to update following update' do
p #employee
put :update, params: {
id: #employee[:id],
employee: { name: "New Name" }
}
#employee.reload
p #employee
expect(#employee.name).to eq("New Name")
end
end
The test fails and #employee.name remains unchanged. I have a feeling the update it not even occurring because I added a print line to my controller and I do not see it in my logs:
def update
p "IN UPDATE"
if #employee.update(employee_params)
redirect_to edit_employee_path(#employee[:id])
else
render :edit
end
end
Is there something I am missing in my put call?

Rails controller tests with devise sign in unexpected behavior

I am trying to create a simple tests on my application with devise. I have a redirect set up if the user is not logged in, but even though I use sign_in before the test I still get redirected. When I manually test this, it works fine.
users.yml
george:
name: George
email: george#example.com
encrypted_password: <%= Devise::Encryptor.digest User, '123456' %>
addresses.yml
georges_home:
title: Home
receiver: George
street: '132 Mitchell St SW'
country: 'US'
city: 'Atlanta'
postal_code: '30303'
phone: '+1 404-524-5665'
state: 'Georgia'
user: george
addresses_controller.rb
class AddressesController < ApplicationController
before_action :login_needed
def index
#addresses = Address.where(user_id: #current_user.id)
end
private
def login_needed
if !user_signed_in?
redirect_to new_user_session_path, alert: 'Please log in.'
end
end
end
addresses_controller_test.rb
require 'test_helper'
class AddressesControllerTest < ActionController::TestCase
include Devise::TestHelpers
setup do
sign_in users(:george)
#address = addresses(:georges_home)
end
test "should get index" do
get :index
assert_response :success
assert_not_nil assigns(:addresses)
end
end
I found a piece of code that was dealing with fixtures of a User model with devise and the confirmable option. So my users' fixture should look like this:
users.yml
george:
name: George
email: george#example.com
encrypted_password: <%= Devise::Encryptor.digest User, '123456' %>
confirmed_at: <%= Date.today %>

Testing my models method in rails

I have to test the creation of my account. This is my Account.create() in controllers method.
Account.create( account: { name: "#{params[:account][:name]}",
description: "#{params[:description]}" }, user: { email: current_user.name })
I have to test my model method Account.create().
post :create, '/account'
Below is my spec class.
require 'spec_helper'
describe Account do
before(:all) do
end
it "can create an account" do
FactoryGirl.create :account, name: "something", description: "something"
# Account.create()
end
end
I am not sure on how to procced.
FactoryGirl is a tool to use when the methods you want to test need a complicated predefined state. When account creation has no dependencies you could simply do something like:
it "can create an account" do
acc = Account.create(name: 'something', description:'something')
acc.name.should == 'something'
acc.description.should == 'something'
end
Please, take a look at this article, it explains how to test Models.
I your case it should be like this:
it "can create an account" do
FactoryGirl.create(:account, name: "something", description: "something").should be_valid
end

How to post to create with spec helper method in controller spec?

I'm relatively new to programming, Rails, Ruby, Rspec, and the like, so thanks for your help!
My specs were very repetitive, so I wrote some spec helper methods. I can't figure out how to properly use them in my specs. Specifically, I have a users controller with create:
def create
#user = User.new(params[:user])
if #user.save
redirect_to user_path(#user)
else
render :action => :new
end
end
A bit in the spec helper that creates a valid user:
def valid_user_eilif
#test_image = Rails.root + "spec/fixtures/images/seagull.jpg"
#file = Rack::Test::UploadedFile.new(#test_image, "image/jpeg")
user = User.create!(:username => "eilif", :email => "eilif#email.org",
:image => #file, :bio => "Lots of text that I don't want to write",
:signature_quote => "Yet more text.")
user.save!
user
end
And then in my user controller spec:
before (:each) do
post :create, :user => valid_user_eilif
end
it 'should assign user to #user' do
assigns(:user).should eq(User.last)
end
When I run the spec I get the error:
Failure/Error: assigns(:user).should eq(User.last)
expected #<User id: 1, username: "eilif", email: "eilif#email.org", bio: "Lots of text that I don't want to write", signature_quote: "I feel empty.", image_file_name: "seagull.jpg", image_content_type: "image/jpeg", image_file_size: 10475, image_updated_at: "2011-05-10 23:35:55", created_at: "2011-05-10 23:35:56", updated_at: "2011-05-10 23:35:56">
got #<User id: nil, username: nil, email: nil, bio: nil, signature_quote: nil, image_file_name: nil, image_content_type: nil, image_file_size: nil, image_updated_at: nil, created_at: nil, updated_at: nil>
So, I assume I'm incorrectly posting to create, since nothing is created? What's the proper way to do this?
Ideally controller specs shouldn't depend on the model being able to create a row in the database. With such a simple action you can mock out the dependencies:
describe UsersController do
context "on success" do
before(:each) do
#user = mock_model(User,:save=>true)
User.stub(:new) {#user}
post :create, :user => {}
end
it "redirects" do
response.should redirect_to(user_path(#user))
end
it "assigns" do
assigns[:user].should == #user
end
end
context "on failure" do
it "renders 'new'" do
#user = mock_model(User,:save=>false)
User.stub(:new) {#user}
post :create, :user => {}
response.should render_template "users/new"
end
end
end
Notice that the specs don't pass anything in params[:user]. This helps enforce the MVC separation of concerns, whereby the model is responsible for handling the attributes, ie. validating, setting up associations, etc. You can't always keep controllers this 'skinny', but it's a good idea to try.
It looks like the problem is that #user doesn't get refreshed after the save. Try assigns(:user).reload.should eql(User.last).
But there's another slight problem, and that's probably still going to fail. You shouldn't be calling post with :user => valid_user_eilif; you want the attributes from your user record, not the actual user object itself. And you're essentially creating a new user in valid_user_eilif and then making your controller create that object again -- if you have any kind of unique constraints, you're going to get a conflict.
This is a good place to use something like factory_girl and mocks. For an example, take a look at how one of my projects handles controller specs. This example uses factory_girl, Mocha and shoulda. I'll annotate it with comments below:
describe MembersController, "POST create" do
before do
# Factory Girl - builds a record but doesn't save it
#resource = Factory.build(:member)
# Mocha expectation - overrides the default "new" behavior and makes it
# return our resource from above
Member.expects(:new).with({}).returns(#resource)
# Note how we expect it to be called with an empty hash; that's from the
# `:member` parameter to `post` below.
end
context "success" do
before do
post :create, :member => {}
end
# shoulda matchers - check for a flash message and a redirect
it { should set_the_flash.to(/successfully created/) }
it { should redirect_to(member_path(#resource)) }
end
context "failure" do
before do
# Mocha - To test a failing example in the controller, we override the
# default `save` behavior and make it return false, otherwise it would
# be true
#resource.expects(:save).returns(false)
post :create, :member => {}
end
# shoulda matchers - check for no flash message and re-render the form
it { should_not set_the_flash }
it { should render_template(:new) }
end
end

Resources