了解如何使用RSpec

时间:2016-02-17 08:23:30

标签: ruby-on-rails ruby rspec

我希望从这个问题中获得的主要内容是理解。在一些帮助下,我一直在考虑将我的控制器代码重构为更易于管理的模块/类,以便我可以有效地测试它们。我在这里有一个例子,我想继续研究,我的问题是如何测试班级Sale

class TransactionsController < ApplicationController
  def create
    payment = BraintreeTransaction::VerifyPayment.new(params, @user_id, @transaction_total)
    payment.run(params)

  if payment.success?
    redirect_to thank_you_path
  else
    flash.now[:alert] = payment.error
    flash.keep
    redirect_to new_transaction_path
  end
end

module BraintreeTransaction
  class VerifyPayment
    def initialize(params, user_id, total)
      @transaction_total = total
      @user_id = user_id
      @params = params
      @error_message = nil
   end

  def run(params)
    @result = BraintreeTransaction::Sale.new.braintree_hash(params, @transaction_total)
    if @result.success?
      @cart_items = CartItem.where(user_id: @user_id).where.not(image_id: nil)
     @cart_items.destroy_all
     create_real_user
     update_completed_transaction
     guest_user.destroy
     @success = true
  else
    update_transaction
    @error_message = BraintreeErrors::Errors.new.error_message(@result)
  end
end

  def success?
    @success
  end

  def error
    @error_message
  end
end 

module BraintreeTransaction
  class Sale
    def braintree_hash(params, total)
      Braintree::Transaction.sale(
        amount: total,
        payment_method_nonce: params[:payment_method_nonce],
        device_data: params[:device_data],
        customer: {
          first_name: params[:first_name],
          last_name: params[:last_name],
          email: params[:email],
          phone: params[:phone]
        },
        billing: {
          first_name: params[:first_name],
          last_name: params[:last_name],
          company: params[:company],
          street_address: params[:street_address],
          locality: params[:locality],
       region: params[:region],
         postal_code: params[:postal_code]
       },
       shipping: {
        first_name: params[:shipping_first_name].presence || params[:first_name].presence,
      last_name: params[:shipping_last_name].presence || params[:last_name].presence,
        company: params[:shipping_company].presence || params[:company].presence,
      street_address: params[:shipping_street_address].presence || params[:street_address].presence,
         locality: params[:shipping_locality].presence || params[:locality].presence,
      region: params[:shipping_region].presence || params[:region].presence,
      postal_code: params[:shipping_postal_code].presence || params[:postal_code].presence
    },
    options: {
      submit_for_settlement: true,
      store_in_vault_on_success: true
    }
  )
  end
 end
end

我不知道我是否正在查看这个错误,但这段代码BraintreeTransaction::Sale.new.braintree_hash是我想要测试的,我想确保在调用时类接收哈希?

更新

到目前为止,我已经提出了这个问题(虽然我不是100%确信这是正确的方法吗?)

require 'rails_helper'
RSpec.describe BraintreeTransaction::Sale do
 @transaction_total = 100
 let(:params) { FactoryGirl.attributes_for(:braintree_transaction, amount: @transaction_total) }
 it 'recieves a hash when creating a payment' do
  expect_any_instance_of(BraintreeTransaction::Sale).to receive(:braintree_hash).with(params, @transaction_total).and_return(true)
 end
end

我收到错误,我不明白

Failure/Error: DEFAULT_FAILURE_NOTIFIER = lambda { |failure, _opts| raise failure }
Exactly one instance should have received the following message(s) but didn't: braintree_hash

2 个答案:

答案 0 :(得分:0)

我可能不会参与,但我会回答我解决这个问题的方式。有三种方法可以编写测试来测试您要测试的代码。

  • braintree_hash对象
  • BraintreeTransaction::Sale编写单元测试
  • create controller
  • 中为TransactionsController方法编写控制器单元方法
  • create中的TransactionsController方法编写路由的集成测试。

这些是您可以开始探索的方式。

答案 1 :(得分:0)

这里有几件事。重构代码的所有建议(来自您的其他问题Writing valuable controller tests - Rspec)都适用于此处。如果有帮助,我可以就此代码提出进一步的建议。

在您的测试中,我认为您的问题是您从未实际调用<div id="click" onclick="change()">click</div> <div id="content">content</div> <script src="test.js"></script> (应在BraintreeTransaction.new.braintree_hash(params)声明后立即调用)。所以没有任何实例收到消息。