我正在尝试测试一个预订模型的创建,该模型涉及在创建时使用ActiveMerchant处理付款。
ActiveMerchant Railscast之后涉及的支付处理的初始设置。付款在应用程序中正常运行。 (http://railscasts.com/episodes/145-integrating-active-merchant)
我已尝试在credit_card
工厂内及其自己的“{valid_credit_card”工厂内创建Reservation
对象...
基本测试只是试图验证可以创建预约。 测试结果:
1) Reservation should have a valid factory
Failure/Error: @current_reservation = Factory.create(:reservation)
NoMethodError:
undefined method `credit_card=' for #<Reservation:0xb5f6173c>
# ./spec/models/reservation_spec.rb:11
预订属于用户,并且has_many rooms通过reservation_sets
Factory.define :reservation do |f|
f.association :user
f.rooms { |a| [a.association(:room)] }
f.arrival Time.now + 2.weeks
f.nights 2
f.phone "555-123-1234"
f.credit_card :valid_credit_card
end
Factory.define :valid_credit_card, :class => ActiveMerchant::Billing::CreditCard do |f|
expiration_date = Time.zone.now + 1.year
f.type "visa"
f.number "4111111111111111"
f.verification_value "333"
f.month expiration_date.strftime("%m")
f.year expiration_date.strftime("%y")
f.first_name "Bob"
f.last_name "Smith"
end
spec / models / reservation_spec.rb。使用@credit_card Factory.build会导致有关“保存”credit_card的错误。
如果我删除了行f.credit_card:valid_credit_card,我得到:month
的NoMethodError
即使:month
中列出了attr_accessor
。在应用程序中创建预订确实有效。
1) Reservation should have a valid factory
Failure/Error: @current_reservation = Factory.create(:reservation)
NoMethodError:
undefined method `month' for nil:NilClass
describe Reservation do
before :each do
@smith = Factory.create(:user)
@room = Factory.create(:room)
#@credit_card = Factory.build(:valid_credit_card)
end
it "should have a valid factory" do
@current_reservation = Factory.create(:reservation)
@current_reservation.should be_valid
end
end
我忽略了什么/做错了什么......?
预订模型摘录
class Reservation < ActiveRecord::Base
# relationships
belongs_to :user
has_many :reservation_sets,
:dependent => :destroy
has_many :rooms,
:through => :reservation_sets
has_many :transactions,
:class_name => 'ReservationTransaction',
:dependent => :destroy
attr_accessor :card_number, :card_verification, :card_expires_on, :card_type, :ip_address, :rtype, :month, :year
# other standard validations
validate :validate_card, :on => :create
# other reservation methods...
# gets paid upon reservation creation
def pay_deposit
# Generate active merchant object
ReservationTransaction.gateway =
ActiveMerchant::Billing::AuthorizeNetGateway.new({
:login => rooms[0].user.gateway_login,
:password => rooms[0].user.gateway_password
})
response = ReservationTransaction.gateway.purchase(deposit_price_in_cents, credit_card, purchase_options)
t = transactions.create!(:action => "purchase", :amount => deposit_price_in_cents, :response => response)
if response.success?
update_attribute(:reserved_at, Time.now)
# update state
payment_captured!
else
transaction_declined!
errors.add :base, response.message
end
t.card_number = credit_card.display_number
t.save!
response.success?
end
def validate_card
unless credit_card.valid?
credit_card.errors.full_messages.each do |message|
errors.add :base, message #_to_base message
end
end
end
def credit_card
@credit_card ||= ActiveMerchant::Billing::CreditCard.new(
:type => card_type,
:number => card_number,
:verification_value => card_verification,
:month => card_expires_on.month,
:year => card_expires_on.year,
:first_name => first_name,
:last_name => last_name
)
end
来自预约控制器的创建动作
def create
@reservation = Reservation.new(params[:reservation])
@reservation.arrival = session[:arrival]
@reservation.nights = session[:nights]
@reservation.number_kids = session[:number_kids]
@reservation.number_adults = session[:number_adults]
session[:creating_reservation] = 1
@reservation.user_id = @reservation.rooms[0].user_id
session[:owner] = @reservation.user_id
@rooms = Room.all
@reservation.ip_address = request.remote_ip
# get room owner...
@owner = User.find(@reservation.user_id)
respond_to do |format|
if @reservation.save
if @reservation.pay_deposit
#set cc...
@reservation.transactions[0].card_number = @reservation.send(:credit_card).display_number
ReservationMailer.reservation_created(@reservation).deliver
ReservationMailer.reservation_notice(@reservation).deliver
session[:arrival] = nil
session[:reservation_id] = @reservation.id
if @owner
thanks_path = "#{@owner.permalink}/reservations/#{@reservation.id}"
else
thanks_path = @reservation
end
format.html { redirect_to @reservation, :notice => 'Reservation was successfully created.' }
format.json { render :json => @reservation, :status => :created, :location => @reservation }
# also trigger email sending or wherever that is
# receipt email and order notification
#
else
# set flash or show message problem w/ transaction
format.html { render :action => "new" }
end
else
format.html { render :action => "new" }
format.json { render :json => @reservation.errors, :status => :unprocessable_entity }
end
end
end
答案 0 :(得分:0)
您似乎正在尝试为credit_card
分配一个值,但实际上并没有class accessor。因此,您尝试呼叫f.credit_card :valid_credit_card
的地方无效。
我会从您的工厂中移除f.credit_card :valid_credit_card
并查看使用rspec stubs,然后您可以在rspec测试中执行以下操作:
mock_cc = ActiveMerchant::Billing::CreditCard.new(
:type => card_type,
:number => card_number,
:verification_value => card_verification,
:month => card_expires_on.month,
:year => card_expires_on.year,
:first_name => first_name,
:last_name => last_name
)
Reservation.stub(:credit_card).and_return(mock_cc)
当你的模型调用credit_card
时,它会返回一个模拟对象。