我有一个truncation
数据库清理策略,所以不确定为什么会这样。基本上,只需执行一个功能说明即可测试订单是否已正确创建。
require 'rails_helper'
describe "create successfully", type: :feature, js: true do
before do
@site = create(:site)
visit "/orders"
.... # various actions to build an order using the page's form
puts ">>>>>"
puts "site in before action: #{Site.all.size}"
find("#checkoutModal #submit").click()
sleep(1)
end
it "should create" do
expect(Order.all.size).to equal(1)
end
end
# controller action that #submit POSTs to
def create
puts ">>>>>"
puts "site in controller create: #{Site.all.size}"
@order = Order.new(order_params)
@order.save if @order.valid?
end
# puts output:
>>>>>
site in before action: 1
>>>>>
site in controller create: 0
该规范失败,因为@order的创建取决于@site
。关于为什么@site被销毁有什么想法?同样,我确实设置了正确的截断:
# rails_helper.rb
Rspec.configure do |config|
config.use_transactional_fixtures = false
config.before(:each) do
DatabaseCleaner.strategy = :transaction
end
config.before(:each, js: true) do
DatabaseCleaner.strategy = :truncation
end
config.before(:each, truncate: true) do
DatabaseCleaner.strategy = :truncation
end
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
end
一种更好的测试方法是使用change匹配器:
Rspec.feature "Creating orders", js: true do
let!(:site ) { create(:site) }
def fill_in_and_submit_form
visit "/orders"
# ...
fill_in "something", with: attributes[:something]
find("#checkoutModal #submit").click()
end
context "with valid attributes" do
let(:attributes){ attributes_for(:order) }
it "creates an order" do
expect do
fill_in_and_submit_form
end.to change(Order, :count).by(1)
end
end
context "with invalid attributes" do
let(:attributes) do
{} # should be a hash with invalid attributes
end
it "does not create an order" do
expect do
fill_in_and_submit_form
end.to_not change(Order, :count)
end
end
end
这将在计算块之前和之后创建计数查询。使用.size
应该记住的一件事是,如果集合已经被加载,它将返回集合的长度。这不是一件好事,因为您需要数据库计数。
将顶级功能描述命名为“成功创建”不是一个好主意。它没有描述您要测试的内容,而是需要创建两个文件来测试成功和失败。
该控制器也完全是错误的。
def create
@order = Order.new(order_params)
if @order.save
redirect_to @order
else
render :new
end
end
@order.save if @order.valid?
很傻。 .save
将验证记录并将其保存(如果有效)。您确实只想检查save的返回值,以查看记录是否实际上已保存到数据库中。如果订单是嵌套记录,则它实际上也应该如下所示:
def create
@site = Site.find(params[:site_id]) # you're not passing it through a hidden input are you?
@order = @site.orders.new(order_params)
if @order.save
redirect_to @order
else
render :new
end
end