1

我正在使用最新版本的 Solidus 电子商务(Spree 的分支),我遇到了这个问题。快速描述它:

  1. 在 Admin 我创建 Spree::Membership 记录
  2. Spree::Membership 中的 after_save 回调创建 Product 和 2 个变体

此代码在我运行服务器时有效,但是当我尝试使用 Rspec 时,它给了我这个错误:

Failure/Error: reload.product.setup_membership_variants

 NoMethodError:
   undefined method `setup_membership_variants' for nil:NilClass
 # ./app/models/spree/membership.rb:26:in `block in setup_product'
 # ./app/models/spree/membership.rb:18:in `setup_product'
 # /box/gems/factory_girl-4.8.0/lib/factory_girl/configuration.rb:18:in `block in initialize'
 # /box/gems/factory_girl-4.8.0/lib/factory_girl/evaluation.rb:15:in `create'
 # /box/gems/factory_girl-4.8.0/lib/factory_girl/strategy/create.rb:12:in `block in result'
 # /box/gems/factory_girl-4.8.0/lib/factory_girl/strategy/create.rb:9:in `tap'
 # /box/gems/factory_girl-4.8.0/lib/factory_girl/strategy/create.rb:9:in `result'
 # /box/gems/factory_girl-4.8.0/lib/factory_girl/factory.rb:42:in `run'
 # /box/gems/factory_girl-4.8.0/lib/factory_girl/factory_runner.rb:29:in `block in run'
 # /box/gems/factory_girl-4.8.0/lib/factory_girl/factory_runner.rb:28:in `run'
 # /box/gems/factory_girl-4.8.0/lib/factory_girl/strategy_syntax_method_registrar.rb:20:in `block in define_singular_strategy_method'
 # ./spec/controllers/spree/premium_controller_spec.rb:4:in `block (2 levels) in <top (required)>'
 # ./spec/controllers/spree/premium_controller_spec.rb:33:in `block (6 levels) in <top (required)>'
 # ./spec/controllers/spree/premium_controller_spec.rb:53:in `block (8 levels) in <top (required)>'
 # ./spec/controllers/spree/premium_controller_spec.rb:53:in `block (7 levels) in <top (required)>'

这是我正在使用的代码:

会员资格.rb

class Spree::Membership < Spree::Base

  has_many :active_memberships, class_name: 'Spree::ActiveMembership', dependent: :destroy

  has_one :membership_product, class_name: "Spree::MembershipProduct", dependent: :destroy
  has_one :product, through: :membership_product, source: :product

  validates :name, presence: true
  validates :monthly_quota, presence: true
  validates :price, presence: true

  after_save :setup_product

  private

  def setup_product
    if product.nil?
      ActiveRecord::Base.transaction do
        create_membership_product(
          product: Spree::Product.create(
            name: name, 
            price: price, 
            shipping_category: Spree::ShippingCategory.find_by(name: "Default")
          )
        )
        reload.product.setup_membership_variants
      end
    else
      product.update(name: name, price: price)
    end
  end

end

product_decorator.rb

Spree::Product.class_eval do
  def setup_membership_variants
    ot = Spree::OptionType.find_or_create_by(name: "Membership")
    option_types << ot

    if ot.option_values.empty?
      ["Monthly", "Yearly"].each do |freq|
        ot.option_values.create(name: freq, presentation: freq)
      end
    end


    month = variants.create(is_master: false, price: price, track_inventory: false)
    month.option_values << Spree::OptionValue.find_by(name: "Monthly")
    year = variants.create(is_master: false, price: price * 12, track_inventory: false)
year.option_values << Spree::OptionValue.find_by(name: "Yearly")
  end
end

会员资格.rb工厂

FactoryGirl.define do
  factory :membership, class: Spree::Membership do
    name   {FFaker::Lorem.word}
    monthly_quota { rand(10..200) }
    price { rand(10..200) }

    trait :unnamed do
      name   nil
    end

    trait :without_quota do
      monthly_quota nil
    end

    trait :priceless do
      price nil
    end
  end
end

控制器测试示例

require 'rails_helper'

RSpec.describe Spree::PremiumController, type: :controller do
  let(:valid_membership) { create(:membership) }
  let(:variant) { create(:master_variant) }

  context "#show" do
    it "returns http success" do
      get :show
      expect(response).to have_http_status(:success)
    end
    it "returns all memberships" do 
      get :show
      expect(assigns[:memberships]).to include(valid_membership)
    end
  end

  context "#create" do 
    let!(:store) { create(:store) }

    context "user not logged" do 

      context "valid attributes" do
        context "user doesn't exist in database" do
          subject do
            post(:create, params: { 
              premium: { 
                first_name: "Ondrej", 
                last_name: "Kubala", 
                email: "ondrej@bala.com", 
                password: "test123",
                password_confirmation: "test123",
                membership_id: valid_membership.id, 
                payment_frequency: "1", #monthly yearly is 2 
                cc_number: "4111111111111111", 
                cc_exp_date: "10/22", 
                cvv: "123"
              }
            }) 
          end

          it "creates user with valid attributes" do 
            expect { subject }.to change { Spree::User.count }.from(0).to(1)
          end

          it "logs in user" do 
            expect(controller.warden).to receive(:set_user)
            subject
          end

          context "create order with variant" do
            it "should handle population" do 
              expect { subject }.to change { Spree::Order.count }.by(1)
              user = Spree::User.find_by email: "ondrej@bala.com"

              order = user.orders.last
              expect(response).to redirect_to go_premium_path

              expect(order.line_items.size).to eq(1)
              # line_item = order.line_items.first
              # expect(line_item.variant_id).to eq(valid_membership.reload.product.variants.)
            end
            it "charges credit card"
            it "should redirect to account page"
          end
        end

        context "user already exists"
      end

      context "wrong user attributes" do

      end

      context "wrong payment attributes" do 

      end
    end

    context "user is logged in" do 
      let(:user) { create(:user) }

      before do
        allow(controller).to receive_messages try_spree_current_user: user
        allow(controller).to receive_messages spree_current_user: user
      end

      it "doesn't create user"
    end
  end
end

我在 Rspec 方面没有太多经验,但是很奇怪,当服务器在开发中运行时它可以工作,但在测试中它给了我这个错误。

知道有什么问题吗?

4

1 回答 1

0

我的猜测是产品创建调用由于某种原因而失败。尝试 bang version( product: Spree::Product.create!) 以在错误发生时抛出错误。

如果产品确实被创建,使用prybyebug找出reload成员资格后的原因,产品与membership.

于 2017-08-06T00:32:38.310 回答