如何使用RSpec和Factory_Bot测试Payola? (用户创建)

时间:2018-01-15 02:00:41

标签: ruby-on-rails ruby rspec factory-bot

我一直在尝试为我的用户模型构建一个工厂,当我尝试手动将值放入工厂定义中时,我似乎无法通过ActiveRecord :: AssociationTypeMismatch SubscriptionPlan。我不知道如何将subscription_plan传递给用户对象。如何使用factory_bot创建用户并附加订阅计划以获取传递规范?我写的代码如下,包括错误信息。

控制台错误

require 'rails_helper'

RSpec.describe User, type: :model do
  it "should be able to create a user with factory bot" do
    user = FactoryBot.create(:user, first_name: 'Daniel', subscription_plan: "Silver Plan")
    expect(user.first_name).to eq('Daniel')
  end
end

user_spec.rb

FactoryBot.define do
  sequence :email do |n|
    "person#{n}@example.com"
  end
end

FactoryBot.define do

  factory :user, :class => 'User' do
    email
    username "david101"
    first_name "David"
    last_name "Jones"
    state "New York"
    password "Golden20305@!"
    password_confirmation "Golden20305@!"
    subscription_plan
  end
end

users.rb(RSpec)

class User < ApplicationRecord
  enum role: [:user, :silver, :gold]
  second_level_cache expires_in: 1.week
  # Include default devise modules.
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable,
         :confirmable
  include DeviseTokenAuth::Concerns::User
  before_create :build_user_profile
  geocoded_by :last_sign_in_ip, :latitude => :lat, :longitude => :lon
  geocoded_by :user_address, :latitude => :lat, :longitude => :lon

  after_validation :geocode

  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
  friendly_id :username, use: :slugged
  belongs_to :subscription_plan
  accepts_nested_attributes_for :user_profile, update_only: true
  acts_as_messageable

  # Validations
  validates_associated :subscription_plan
  validates :email, presence: true, uniqueness: true, email: {strict_mode: true}
  validates :username, presence: true, length: {maximum: 15, minimum: 2},
            format: {with: /\A[a-zA-Z0-9]+\Z/}, uniqueness: true
  validates :first_name, presence: true, uniqueness: false, length: {maximum: 50}, format: {with: /\A[a-zA-Z]+(?: [a-zA-Z]+)?\z/}
  validates :last_name, presence: true, uniqueness: false, length: {maximum: 50}, format: {with: /\A[a-zA-Z]+(?: [a-zA-Z]+)?\z/}
  validates :country, presence: true
  validates :state, presence: true
  validates :street, presence: true
  validates :city_or_town, presence: true, length: {maximum: 60, minimum: 2}
  validates :zip_code, presence: true, length: {maximum: 50}, format: {with: /\A[a-z0-9\s]+\Z/i}
  validates :password, password_strength: {use_dictionary: true}

  def set_default_role
    self.role ||= :silver
  end

  def set_default_plan
    self.subscription_plan ||= Plan.last
  end

  def stripe_membership_checker
    case
      when self.subscription_plan_id.nil?
        "Normal User"
      when self.subscription_plan_id == 5
        "Gold"
      when self.subscription_plan_id == 4
        "Silver"
      else
        ""
    end
  end

  protected
  def confirmation_required?
    false
  end
end

user.rb

class SubscriptionPlan < ApplicationRecord
  include Payola::Plan
  has_many :users

  scope :user_plan, -> {where(stripe_id: %w(silver gold))}

  def redirect_path(subscription)
    '/'
  end
end

subscription_plan.rb

<%= simple_form_for(resource, as: resource_name, url: registration_path(resource_name), :html => {:role => 'form',
                                                                                                      :class => 'payola-onestep-subscription-form',
                                                                                                      'data-payola-base-path' => payola_path,
                                                                                                      'data-payola-plan-type' => resource.subscription_plan.class, 'data-payola-plan-id' => resource.subscription_plan}) do |f| %>

        <div class="form-group">
          <div class="col-5">
            <%= f.error_notification %>
            <%= devise_error_messages! %>
            <span class="payola-payment-error"></span>
          </div>
        </div>
        <div class="form-group">
          <label class="col-5 col-form-label">Monthly Subscription Plan</label>
          <div class="col-4">
            <%= f.association :subscription_plan, collection: SubscriptionPlan.user_plan.map {|c| [c.name, c.id]}, label: false, prompt: 'Choose a plan' %>
          </div>
        </div>
        <div class="form-group">
          <label for="fg-1" class="col-4 col-form-label">Email</label>
          <div class="col-4">
            <%= f.input :email, label: false, required: true, autofocus: true, id: 'fg-1', placeholder: 'What is your email address?' %>
          </div>
        </div>

new.html.erb(新用户)

{{1}}

1 个答案:

答案 0 :(得分:0)

不要伤害自己。

user = FactoryBot.create(:user, first_name: 'Daniel', subscription_plan: "Silver Plan")

我不知道你的subscription_plans.rb工厂是什么样的,但是你需要传递一个SubscriptionPlan ActiveRecord对象而不是"Silver Plan"

我通过查看此错误ActiveRecord::AssociationTypeMismatch: SubscriptionPlan(#75441564) expected, got "Silver Plan" which is an instance of String(#36231624)

来到这里

这表明没有正确设置。