我正在使用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协会是打破控制器测试的原因。如何解决问题并再次通过控制器测试?谢谢你的帮助!
答案 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',因为我不确定该字段的名称是什么,所以只需使用它的名称。