我正在使用最新版本的 Solidus 电子商务(Spree 的分支),我遇到了这个问题。快速描述它:
- 在 Admin 我创建 Spree::Membership 记录
- 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 方面没有太多经验,但是很奇怪,当服务器在开发中运行时它可以工作,但在测试中它给了我这个错误。
知道有什么问题吗?