失败的Rails 4控制器测试 - ActiveRecord :: AssociationTypeMismatch?

时间:2015-12-23 20:50:44

标签: postgresql ruby-on-rails-4 activerecord rspec factory-bot

我正在使用Postgres(0.18.3),Rspec(3.1.0)和FactoryGirl(4.5.0)构建Rails(4.1.8)应用程序。我需要帮助对控制器测试进行故障排除,这会导致FactoryGirl对象导致Active Record :: AssociationTypeMismatch错误。

这是我的健身目标控制器指数行动:

def index
  @fitness_goals = @member.fitness_goals.order(:start_date)    
end

这是我对健身目标控制器索引动作的设置和测试(fitness_goals_controller_spec.rb):

RSpec.describe FitnessGoalsController, :type => :controller do

let(:member_attributes) { { 

  "first_name" => 'Joe',
  "last_name" => 'Smith',
  "sex" => 'Male', 
  "age" => 30,
  "height" => 69,
  "weight" => 187,
  "goal" => ["Lose Fat"],
  "start_date" => Date.current    
  }
 }  

before :each do
  @request.env["devise.mapping"] = Devise.mappings[:user]
  @user = FactoryGirl.create(:user)
  sign_in @user

  @member = @user.build_member member_attributes
  @member.save

  @fitness_goal = FactoryGirl.create(:fitness_goal, member: @member)
  @fitness_goal_attributes = FactoryGirl.build(:fitness_goal).attributes
  @fitness_goal_invalid_attributes = FactoryGirl.build(:fitness_goal, timeframe_id: nil).attributes
  @fitness_goal_update_attributes = FactoryGirl.build(:fitness_goal).attributes
  @fitness_goal_update_invalid_attributes = FactoryGirl.build(:fitness_goal, timeframe_id: nil).attributes
end

describe "GET index" do
  it "assigns all fitness goals as @member.fitness_goals" do
    get :index, { :member_id => @member  }
    expect(assigns(:fitness_goals)).to eq(@member.reload.fitness_goals)
  end
end

rspec错误和回溯:

1) FitnessGoalsController GET index assigns all fitness goals as @member.fitness_goals
 Failure/Error: @fitness_goal = FactoryGirl.create(:fitness_goal, member: @member)
 ActiveRecord::AssociationTypeMismatch:
   Target(#62887900) expected, got String(#8489780)
 # .rvm/gems/ruby-2.1.5/gems/activerecord-4.1.8/lib/active_record/associations/association.rb:216:in `raise_on_type_mismatch!'
 # .rvm/gems/ruby-2.1.5/gems/activerecord-4.1.8/lib/active_record/associations/collection_association.rb:356:in `block in replace'
 # .rvm/gems/ruby-2.1.5/gems/activerecord-4.1.8/lib/active_record/associations/collection_association.rb:356:in `each'
 # .rvm/gems/ruby-2.1.5/gems/activerecord-4.1.8/lib/active_record/associations/collection_association.rb:356:in `replace'
 # .rvm/gems/ruby-2.1.5/gems/activerecord-4.1.8/lib/active_record/associations/collection_association.rb:41:in `writer'
 # .rvm/gems/ruby-2.1.5/gems/activerecord-4.1.8/lib/active_record/associations/builder/association.rb:118:in `targets='
 # .rvm/gems/ruby-2.1.5/gems/factory_girl-4.5.0/lib/factory_girl/attribute_assigner.rb:16:in `public_send'
 # .rvm/gems/ruby-2.1.5/gems/factory_girl-4.5.0/lib/factory_girl/attribute_assigner.rb:16:in `block (2 levels) in object'
 # .rvm/gems/ruby-2.1.5/gems/factory_girl-4.5.0/lib/factory_girl/attribute_assigner.rb:15:in `each'
 # .rvm/gems/ruby-2.1.5/gems/factory_girl-4.5.0/lib/factory_girl/attribute_assigner.rb:15:in `block in object'
 # .rvm/gems/ruby-2.1.5/gems/factory_girl-4.5.0/lib/factory_girl/attribute_assigner.rb:14:in `tap'
 # .rvm/gems/ruby-2.1.5/gems/factory_girl-4.5.0/lib/factory_girl/attribute_assigner.rb:14:in `object'
 # .rvm/gems/ruby-2.1.5/gems/factory_girl-4.5.0/lib/factory_girl/evaluation.rb:12:in `object'
 # .rvm/gems/ruby-2.1.5/gems/factory_girl-4.5.0/lib/factory_girl/strategy/create.rb:9:in `result'
 # .rvm/gems/ruby-2.1.5/gems/factory_girl-4.5.0/lib/factory_girl/factory.rb:42:in `run'
 # .rvm/gems/ruby-2.1.5/gems/factory_girl-4.5.0/lib/factory_girl/factory_runner.rb:23:in `block in run'
 # .rvm/gems/ruby-2.1.5/gems/activesupport-4.1.8/lib/active_support/notifications.rb:161:in `instrument'
 # .rvm/gems/ruby-2.1.5/gems/factory_girl-4.5.0/lib/factory_girl/factory_runner.rb:22:in `run'
 # .rvm/gems/ruby-2.1.5/gems/factory_girl-4.5.0/lib/factory_girl/strategy_syntax_method_registrar.rb:20:in `block in define_singular_strategy_method'
 # ./spec/controllers/fitness_goals_controller_spec.rb:44:in `block (2 levels) in <top (required)>'

错误引用目标模型,与健身目标模型的has_and_belongs_to_many(HABTM)关联:       目标(#62887900)预期,得到字符串(#8489780)

相关模型:

class FitnessGoal < ActiveRecord::Base
  has_and_belongs_to_many :targets
end

class Target < ActiveRecord::Base   
  has_and_belongs_to_many :fitness_goals
end

架构中的连接表:

create_table "fitness_goals_targets", id: false, force: true do |t|
  t.integer "fitness_goal_id"
  t.integer "target_id"

健身目标参数:

def fitness_goal_params
  params.require(:fitness_goal).permit(:goal_list_id, :timeframe_id, :start_date, :end_date, { target_ids: [] }, { activity_ids: [] }, :notes, :member_id, :trainer_id)
end

健身目标工厂:

FactoryGirl.define do
  factory :fitness_goal do
association :goal_list
association :timeframe
start_date Date.current
end_date Date.current + 30              
targets ["Lose Fat", "Reduce caloric intake by x%"]
activities ["Walk x steps a day", "Climb x floors a day", "Run x miles a day"]      
association :member
association :trainer
notes 'This is a sample note.'
  end
end

我做错了什么?应用程序代码在开发和生产环境中按预期工作。看来问题出在我对FactoryGirl对象的设置中。实施HABTM协会是打破控制器测试的原因。如何解决问题并再次通过控制器测试?谢谢你的帮助!

1 个答案:

答案 0 :(得分:0)

您需要更改工厂以将Target对象而不是字符串传递给该关联。因此,您需要创建Target对象(或者找到它们,如果它们已经存在)。变化

targets ["Lose Fat", "Reduce caloric intake by x%"]

targets { [create(:target, field: "Lose Fat"), create(:target, field: "Reduce caloric intake by x%")] }

我使用的标签是'field',因为我不确定该字段的名称是什么,所以只需使用它的名称。