Rspec 的预期更改计数不起作用
Rspec's expect change count not working
我在这里测试当前用户发送有效消息后 current_user.messages.count
中的变化。这是我的代码:
规格
scenario 'adds to their messages', js: true do
expect { find('#message_content').send_keys(:enter) }.to \
change(current_user.messages, :count).by(1)
end
test.log
# ...
ConversationChannel is transmitting the subscription confirmation
ConversationChannel is streaming from conversation_channel_1
(0.6ms) SELECT COUNT(*) FROM "messages" WHERE "messages"."user_id" = [["user_id", 1]]
ConversationChannel#send_message({"content"=>"foobar\n", "conversation_id"=>"1"})
(0.3ms) BEGIN
(0.9ms) SELECT COUNT(*) FROM "messages" WHERE "messages"."user_id" = [["user_id", 1]]
Conversation Load (1.6ms) SELECT "conversations".* FROM "conversations" WHERE "conversations"."id" = LIMIT [["id", 1], ["LIMIT", 1]]
(0.7ms) SELECT "users"."id" FROM "users" INNER JOIN "user_conversations" ON "users"."id" = "user_conversations"."user_id" WHERE "user_conversations"."conversation_id" = [["conversation_id", 1]]
SQL (1.0ms) INSERT INTO "messages" ("content", "user_id", "conversation_id", "created_at", "updated_at") VALUES (, , , , ) RETURNING "id" [["content", "foobar\n"], ["user_id", 1], ["conversation_id", 1], ["created_at", "2018-01-29 11:27:13.095277"], ["updated_at", "2018-01-29 11:27:13.095277"]]
Finished "/cable/" [WebSocket] for 127.0.0.1 at 2018-01-29 19:27:13 +0800
ConversationChannel stopped streaming from conversation_channel_1
(0.2ms) BEGIN
(58.8ms) COMMIT
(16.7ms) ALTER TABLE "schema_migrations" DISABLE TRIGGER ALL;ALTER TABLE "ar_internal_metadata" DISABLE TRIGGER ALL;ALTER TABLE "conversations" DISABLE TRIGGER ALL;ALTER TABLE "messages" DISABLE TRIGGER ALL;ALTER TABLE "user_conversations" DISABLE TRIGGER ALL;ALTER TABLE "users" DISABLE TRIGGER ALL
Rendered messages/_message.html.erb (0.6ms)
[ActionCable] Broadcasting to conversation_channel_1: {:message=>"<p>User 1: foobar\n</p>\n"}
# ...
规范失败 expected #count to have changed by 1, but was changed by 0
,即使在日志中显示 INSERT INTO
确实发生了。
试着写:
改变{current_user.messages, :count}.by(1)
与 {}
这不起作用,因为您等待消息添加的时间不够长。 send_keys
returns 一旦浏览器发送了按键事件,但对浏览器中该按键触发的任何 request/action 一无所知。这就是为什么直接数据库访问测试在 feature/system 测试中通常不是一个好主意(通常应该只测试用户可见 changes/interactions)并且作为请求或控制器更有意义。
据说您可以通过在发送密钥后休眠来解决此问题,但更好的解决方案是使用 Capybara 提供的匹配器之一(具有 waiting/retrying 行为)来同步测试。
scenario 'adds to their messages', js: true do
expect do
find('#message_content').send_keys(:enter) }
expect(page).to have_css(...) # check for whatever visible change on the page indicates the action triggered by send_keys has completed
end.to change { current_user.reload.messages.count }.by(1)
end
注意:这个测试对于特性测试来说也是非常简单的。在功能测试中有多个期望是可以的,因为它实际上是为了测试整个用户与应用程序特定功能的交互。您可能希望将此测试与应用同一部分的其他测试相结合。
我在这里测试当前用户发送有效消息后 current_user.messages.count
中的变化。这是我的代码:
规格
scenario 'adds to their messages', js: true do
expect { find('#message_content').send_keys(:enter) }.to \
change(current_user.messages, :count).by(1)
end
test.log
# ...
ConversationChannel is transmitting the subscription confirmation
ConversationChannel is streaming from conversation_channel_1
(0.6ms) SELECT COUNT(*) FROM "messages" WHERE "messages"."user_id" = [["user_id", 1]]
ConversationChannel#send_message({"content"=>"foobar\n", "conversation_id"=>"1"})
(0.3ms) BEGIN
(0.9ms) SELECT COUNT(*) FROM "messages" WHERE "messages"."user_id" = [["user_id", 1]]
Conversation Load (1.6ms) SELECT "conversations".* FROM "conversations" WHERE "conversations"."id" = LIMIT [["id", 1], ["LIMIT", 1]]
(0.7ms) SELECT "users"."id" FROM "users" INNER JOIN "user_conversations" ON "users"."id" = "user_conversations"."user_id" WHERE "user_conversations"."conversation_id" = [["conversation_id", 1]]
SQL (1.0ms) INSERT INTO "messages" ("content", "user_id", "conversation_id", "created_at", "updated_at") VALUES (, , , , ) RETURNING "id" [["content", "foobar\n"], ["user_id", 1], ["conversation_id", 1], ["created_at", "2018-01-29 11:27:13.095277"], ["updated_at", "2018-01-29 11:27:13.095277"]]
Finished "/cable/" [WebSocket] for 127.0.0.1 at 2018-01-29 19:27:13 +0800
ConversationChannel stopped streaming from conversation_channel_1
(0.2ms) BEGIN
(58.8ms) COMMIT
(16.7ms) ALTER TABLE "schema_migrations" DISABLE TRIGGER ALL;ALTER TABLE "ar_internal_metadata" DISABLE TRIGGER ALL;ALTER TABLE "conversations" DISABLE TRIGGER ALL;ALTER TABLE "messages" DISABLE TRIGGER ALL;ALTER TABLE "user_conversations" DISABLE TRIGGER ALL;ALTER TABLE "users" DISABLE TRIGGER ALL
Rendered messages/_message.html.erb (0.6ms)
[ActionCable] Broadcasting to conversation_channel_1: {:message=>"<p>User 1: foobar\n</p>\n"}
# ...
规范失败 expected #count to have changed by 1, but was changed by 0
,即使在日志中显示 INSERT INTO
确实发生了。
试着写: 改变{current_user.messages, :count}.by(1) 与 {}
这不起作用,因为您等待消息添加的时间不够长。 send_keys
returns 一旦浏览器发送了按键事件,但对浏览器中该按键触发的任何 request/action 一无所知。这就是为什么直接数据库访问测试在 feature/system 测试中通常不是一个好主意(通常应该只测试用户可见 changes/interactions)并且作为请求或控制器更有意义。
据说您可以通过在发送密钥后休眠来解决此问题,但更好的解决方案是使用 Capybara 提供的匹配器之一(具有 waiting/retrying 行为)来同步测试。
scenario 'adds to their messages', js: true do
expect do
find('#message_content').send_keys(:enter) }
expect(page).to have_css(...) # check for whatever visible change on the page indicates the action triggered by send_keys has completed
end.to change { current_user.reload.messages.count }.by(1)
end
注意:这个测试对于特性测试来说也是非常简单的。在功能测试中有多个期望是可以的,因为它实际上是为了测试整个用户与应用程序特定功能的交互。您可能希望将此测试与应用同一部分的其他测试相结合。