我有一个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
。你有没有想过@网站为什么会被破坏?再次,我确实正确设置了截断:
# 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
测试这一点的更好方法是使用更改匹配器:
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