PUT #update 控制器测试失败,因为它没有修改给定的对象
PUT #update controller test fails as it does not modify given object
我正在尝试使用 rspec 在 rails api 中测试我的更新操作,但是我编写的测试套件似乎无法使用提供的参数更新对象。
在我的 api 中,我有两个模型:Clan 和 Samurai,其中 Samurai 属于 Clan,而 Clan 有很多 Samurai。
我使用 factory bot 生成 fixtures 并且 Clan fixture 在外部范围内定义(因此 clan.id)。
# ../samurais_controller_spec.rb
describe "PUT #update" do
context "with valid attributes" do
let(:new_attributes) { { name: "Danny Boy" } }
let(:new_samurai) { create(:samurai, name: "Danny", clan_id: clan.id) }
it "updates samurai" do
put :update, params: { clan_id: new_samurai.clan_id,
id: new_samurai.id,
samurai: new_attributes }
new_samurai.reload
expect(new_samurai.name).to eq(new_attributes[:name])
end
end
end
# ../samurais_controller.rb
def update
samurai.update!(samurai_params)
render json: samurai.to_json
end
...
private
def clan
@clan ||= Clan.find(params[:clan_id])
end
def samurai
@samurai ||= Samurai.find_by!(id: params[:id], clan_id: params[:clan_id])
end
def samurai_params
params.permit(:name, :death_date, :armor_quality, :number_of_battles, :join_date)
end
每当我 运行 rspec 我收到这个错误:
1) Clans::SamuraisController PUT #update with valid attributes updates samurai
Failure/Error: expect(new_samurai.name).to eq(new_attributes[:name])
expected: "Danny Boy"
got: "Danny"
(compared using ==)
# ./spec/controllers/samurais_controller_spec.rb:84:in `block (4 levels) in <main>'
这让我有点困惑,因为当我在控制台中 运行 samurai.update! some_params
它工作正常。
我认为问题在于测试套件不知何故没有更新正确的 samurai,所以我尝试用以下代码对其进行存根:
before(:each) do
Samurai.should_receieve(:find).and_return(new_samurai)
end
但它不起作用(并且已弃用)。
我很乐意提供帮助。
更新:
# ../schema.rb
ActiveRecord::Schema.define(version: 2019_03_14_150921) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "clans", force: :cascade do |t|
t.string "name", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "samurais", force: :cascade do |t|
t.string "name", null: false
t.integer "armor_quality", default: 0
t.integer "number_of_battles", default: 0
t.date "join_date"
t.date "death_date"
t.bigint "clan_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["clan_id"], name: "index_samurais_on_clan_id"
end
add_foreign_key "samurais", "clans"
end
您必须将控制器中的 samurai_params
方法更改为:
def samurai_params
params.require(:samurai).permit(:name, :death_date, :armor_quality, :number_of_battles, :join_date)
end
或者修改您的规范以直接发送新属性(不将它们嵌套在散列中):
request_params = { clan_id: new_samurai.clan_id, id: new_samurai.id }
request_params.merge!(new_attributes)
put :update, params: request_params
我正在尝试使用 rspec 在 rails api 中测试我的更新操作,但是我编写的测试套件似乎无法使用提供的参数更新对象。
在我的 api 中,我有两个模型:Clan 和 Samurai,其中 Samurai 属于 Clan,而 Clan 有很多 Samurai。 我使用 factory bot 生成 fixtures 并且 Clan fixture 在外部范围内定义(因此 clan.id)。
# ../samurais_controller_spec.rb
describe "PUT #update" do
context "with valid attributes" do
let(:new_attributes) { { name: "Danny Boy" } }
let(:new_samurai) { create(:samurai, name: "Danny", clan_id: clan.id) }
it "updates samurai" do
put :update, params: { clan_id: new_samurai.clan_id,
id: new_samurai.id,
samurai: new_attributes }
new_samurai.reload
expect(new_samurai.name).to eq(new_attributes[:name])
end
end
end
# ../samurais_controller.rb
def update
samurai.update!(samurai_params)
render json: samurai.to_json
end
...
private
def clan
@clan ||= Clan.find(params[:clan_id])
end
def samurai
@samurai ||= Samurai.find_by!(id: params[:id], clan_id: params[:clan_id])
end
def samurai_params
params.permit(:name, :death_date, :armor_quality, :number_of_battles, :join_date)
end
每当我 运行 rspec 我收到这个错误:
1) Clans::SamuraisController PUT #update with valid attributes updates samurai
Failure/Error: expect(new_samurai.name).to eq(new_attributes[:name])
expected: "Danny Boy"
got: "Danny"
(compared using ==)
# ./spec/controllers/samurais_controller_spec.rb:84:in `block (4 levels) in <main>'
这让我有点困惑,因为当我在控制台中 运行 samurai.update! some_params
它工作正常。
我认为问题在于测试套件不知何故没有更新正确的 samurai,所以我尝试用以下代码对其进行存根:
before(:each) do
Samurai.should_receieve(:find).and_return(new_samurai)
end
但它不起作用(并且已弃用)。
我很乐意提供帮助。
更新:
# ../schema.rb
ActiveRecord::Schema.define(version: 2019_03_14_150921) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "clans", force: :cascade do |t|
t.string "name", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "samurais", force: :cascade do |t|
t.string "name", null: false
t.integer "armor_quality", default: 0
t.integer "number_of_battles", default: 0
t.date "join_date"
t.date "death_date"
t.bigint "clan_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["clan_id"], name: "index_samurais_on_clan_id"
end
add_foreign_key "samurais", "clans"
end
您必须将控制器中的 samurai_params
方法更改为:
def samurai_params
params.require(:samurai).permit(:name, :death_date, :armor_quality, :number_of_battles, :join_date)
end
或者修改您的规范以直接发送新属性(不将它们嵌套在散列中):
request_params = { clan_id: new_samurai.clan_id, id: new_samurai.id }
request_params.merge!(new_attributes)
put :update, params: request_params