Rails 5 - Rspec 期望更改计数不起作用
Rails 5 - Rspec Expect Change Count Not Working
这可能非常简单,但我无法获得 Rspec 的期望更改计数来检测何时通过控制器的创建方法创建新记录。
这是我的测试:
it "saves the new Post in the database" do
expect{
process :create, method: :post, params: { post: attributes_for(:post) }
}.to change{Post.count}.by(1)
end
它只是错误:
expected result to have changed by 1, but was changed by 0
查看 test.log 创建 post 时似乎没有显示任何错误:
[1m[35m (0.0ms)[0m [1m[36mbegin transaction[0m
[1m[35m (0.1ms)[0m [1m[34mSELECT COUNT(*) FROM "posts"[0m
Processing by PostsController#create as HTML
Parameters: {"post"=>{"content"=>"Quas adipisci illum repellat sapiente eos. Quae temporibus facilis. Corporis odit eaque reiciendis eum tempora. Nam dolor sint pariatur.", "excerpt"=>"Dicta veritatis voluptate at. Sed voluptatem corrupti sed impedit quae consequatur. Velit voluptates nisi est nihil. Explicabo qui animi expedita rerum.", "image_url"=>"https://hd.unsplash.com/photo-1413781892741-08a142b23dfe", "keywords"=>"blog, post, key, words", "post_type"=>"article", "published"=>"false", "title"=>"Pariatur laborum ut nostrum quis rem sunt libero."}}
[1m[35m (0.0ms)[0m [1m[35mSAVEPOINT active_record_1[0m
[1m[36mPost Exists (0.1ms)[0m [1m[34mSELECT 1 AS one FROM "posts" WHERE "posts"."title" = ? LIMIT ?[0m [["title", "Pariatur laborum ut nostrum quis rem sunt libero."], ["LIMIT", 1]]
[1m[35m (0.0ms)[0m [1m[31mROLLBACK TO SAVEPOINT active_record_1[0m
Rendering /home/nitrous/code/blog/app/views/posts/index.html.haml within layouts/application
Rendered /home/nitrous/code/blog/app/views/posts/index.html.haml within layouts/application (0.0ms)
Completed 200 OK in 9ms (Views: 0.6ms | ActiveRecord: 0.2ms)
[1m[35m (0.1ms)[0m [1m[34mSELECT COUNT(*) FROM "posts"[0m
[1m[35m (0.1ms)[0m [1m[31mrollback transaction[0m
post 模型验证标题是唯一的。
我可以看到日志显示 'Post Exists' 但如果确实如此,这就是它没有保存新 Post 的原因。这是为什么?
您的 post 变化在这里没有变化一。测试日志中的相关行:
[1m[35m (0.0ms)[0m [1m[31mROLLBACK TO SAVEPOINT active_record_1[0m
"ROLLBACK" 关键字表示您的 post 验证失败,未创建。
您很可能没有在规范开头删除旧帖子,或者没有使用随机数据创建新帖子,这会触发您的唯一性验证。
规范设置期间清除数据库
手动
before { Post.destroy_all }
自动使用数据库清理器:
使用https://github.com/DatabaseCleaner/database_cleaner
RSpec.configure do |config|
config.before(:suite) do
DatabaseCleaner.strategy = :transaction
DatabaseCleaner.clean_with(:truncation)
end
config.around(:each) do |example|
DatabaseCleaner.cleaning do
example.run
end
end
end
在工厂中使用随机数据
使用 Faker gem https://github.com/stympy/faker
FactoryGirl.define do
factory :post do
title { Faker::Lorem.word }
end
end
我建议在每个规范示例运行之前手动清除数据库。当您的应用程序仍然很简单并且每个示例只创建一个或两个模型时,无需添加 gem 来为您完成。
好的,所以我弄清楚了为什么它没有保存新的 Post 记录。无论出于何种原因,未创建应该分配给 :post 工厂中的 post 的作者。这意味着验证失败。
这是我使用的 :post 工厂:
FactoryGirl.define do
factory :post do
title { Faker::Lorem.sentence }
excerpt { Faker::Lorem.paragraph }
content { Faker::Lorem.paragraph }
published false
published_at nil
post_type "article"
keywords "blog, post, key, words"
author
end
end
这是我的 Devise Author 模型的 :author 工厂:
FactoryGirl.define do
factory :author do
email { Faker::Internet.email }
password "password"
password_confirmation "password"
end
end
当我使用 FactoryGirl 生成属性时
attributes_for(:post)
方法,未创建作者,因此未设置 post 的 author_id 属性。
为了解决这个问题,我必须在测试中创建作者,然后在 attributes_for
方法中设置 author_id 属性。
所以我的工作测试现在看起来像这样:
it "saves the new Post in the database" do
author = create(:author)
expect{
process :create, method: :post, params: { post: attributes_for(:post, author_id: author.id) }
}.to change{Post.count}.by(1)
end
尽管这解决了我原来的问题,但我不确定为什么作者没有被创建并关联到 attributes_for
调用中的 Post。
这可能非常简单,但我无法获得 Rspec 的期望更改计数来检测何时通过控制器的创建方法创建新记录。
这是我的测试:
it "saves the new Post in the database" do
expect{
process :create, method: :post, params: { post: attributes_for(:post) }
}.to change{Post.count}.by(1)
end
它只是错误:
expected result to have changed by 1, but was changed by 0
查看 test.log 创建 post 时似乎没有显示任何错误:
[1m[35m (0.0ms)[0m [1m[36mbegin transaction[0m
[1m[35m (0.1ms)[0m [1m[34mSELECT COUNT(*) FROM "posts"[0m
Processing by PostsController#create as HTML
Parameters: {"post"=>{"content"=>"Quas adipisci illum repellat sapiente eos. Quae temporibus facilis. Corporis odit eaque reiciendis eum tempora. Nam dolor sint pariatur.", "excerpt"=>"Dicta veritatis voluptate at. Sed voluptatem corrupti sed impedit quae consequatur. Velit voluptates nisi est nihil. Explicabo qui animi expedita rerum.", "image_url"=>"https://hd.unsplash.com/photo-1413781892741-08a142b23dfe", "keywords"=>"blog, post, key, words", "post_type"=>"article", "published"=>"false", "title"=>"Pariatur laborum ut nostrum quis rem sunt libero."}}
[1m[35m (0.0ms)[0m [1m[35mSAVEPOINT active_record_1[0m
[1m[36mPost Exists (0.1ms)[0m [1m[34mSELECT 1 AS one FROM "posts" WHERE "posts"."title" = ? LIMIT ?[0m [["title", "Pariatur laborum ut nostrum quis rem sunt libero."], ["LIMIT", 1]]
[1m[35m (0.0ms)[0m [1m[31mROLLBACK TO SAVEPOINT active_record_1[0m
Rendering /home/nitrous/code/blog/app/views/posts/index.html.haml within layouts/application
Rendered /home/nitrous/code/blog/app/views/posts/index.html.haml within layouts/application (0.0ms)
Completed 200 OK in 9ms (Views: 0.6ms | ActiveRecord: 0.2ms)
[1m[35m (0.1ms)[0m [1m[34mSELECT COUNT(*) FROM "posts"[0m
[1m[35m (0.1ms)[0m [1m[31mrollback transaction[0m
post 模型验证标题是唯一的。
我可以看到日志显示 'Post Exists' 但如果确实如此,这就是它没有保存新 Post 的原因。这是为什么?
您的 post 变化在这里没有变化一。测试日志中的相关行:
[1m[35m (0.0ms)[0m [1m[31mROLLBACK TO SAVEPOINT active_record_1[0m
"ROLLBACK" 关键字表示您的 post 验证失败,未创建。
您很可能没有在规范开头删除旧帖子,或者没有使用随机数据创建新帖子,这会触发您的唯一性验证。
规范设置期间清除数据库
手动
before { Post.destroy_all }
自动使用数据库清理器:
使用https://github.com/DatabaseCleaner/database_cleaner
RSpec.configure do |config|
config.before(:suite) do
DatabaseCleaner.strategy = :transaction
DatabaseCleaner.clean_with(:truncation)
end
config.around(:each) do |example|
DatabaseCleaner.cleaning do
example.run
end
end
end
在工厂中使用随机数据
使用 Faker gem https://github.com/stympy/faker
FactoryGirl.define do
factory :post do
title { Faker::Lorem.word }
end
end
我建议在每个规范示例运行之前手动清除数据库。当您的应用程序仍然很简单并且每个示例只创建一个或两个模型时,无需添加 gem 来为您完成。
好的,所以我弄清楚了为什么它没有保存新的 Post 记录。无论出于何种原因,未创建应该分配给 :post 工厂中的 post 的作者。这意味着验证失败。
这是我使用的 :post 工厂:
FactoryGirl.define do
factory :post do
title { Faker::Lorem.sentence }
excerpt { Faker::Lorem.paragraph }
content { Faker::Lorem.paragraph }
published false
published_at nil
post_type "article"
keywords "blog, post, key, words"
author
end
end
这是我的 Devise Author 模型的 :author 工厂:
FactoryGirl.define do
factory :author do
email { Faker::Internet.email }
password "password"
password_confirmation "password"
end
end
当我使用 FactoryGirl 生成属性时
attributes_for(:post)
方法,未创建作者,因此未设置 post 的 author_id 属性。
为了解决这个问题,我必须在测试中创建作者,然后在 attributes_for
方法中设置 author_id 属性。
所以我的工作测试现在看起来像这样:
it "saves the new Post in the database" do
author = create(:author)
expect{
process :create, method: :post, params: { post: attributes_for(:post, author_id: author.id) }
}.to change{Post.count}.by(1)
end
尽管这解决了我原来的问题,但我不确定为什么作者没有被创建并关联到 attributes_for
调用中的 Post。