原來的問題
我想寫使用RSpec和水豚和奇蹟,爲什麼我的坤對象始終是空allthough它在我的控制器設置一些功能測試:模型是不可用控制器
app/controllers/timetrackings_controller.rb
:
class TimetrackingsController < ApplicationController
include ApplicationHelper
before_action :authenticate_user!
before_action :set_timetracking, only: [:update, :destroy]
# GET /timetrackings
def index
projects = Project.all_cached.select('id, name, category, number, customer_id').includes(:customer).where(:archived => false).order(:number)
gon.projects = group_by_customer(projects).to_h
gon.services = Service.all_cached.select('id, name').where(:archived => false).order('LOWER(name)')
end
...
現在我想知道爲什麼這個數據不能呈現在我的視圖(save_and_open_page
調試://<![CDATA[ window.gon={};gon.projects={};gon.services=[]; //]]>
),所以我只是試圖讓我的測試文件中坤值:
require 'spec_helper'
describe 'the timetracking page', :js => true do
before :each do
switch_to_subdomain('test')
@project = FactoryGirl.create(:project)
@service = FactoryGirl.create(:service)
user = FactoryGirl.create(:user)
login_as(user, :scope => :user)
visit '/timetracking'
save_and_open_page
end
it 'renders the react component' do
expect(page).to have_selector '#timetracking-form'
end
it 'allows me to create a new timetracking' do
within('#timetracking-form') do
fill_in 'duration', :with => '2'
puts '########'
puts Gon.all_variables
puts Project.all.to_json
puts Service.all.to_json
puts '########'
find_field('project_id').find("option[value='#{@project.id}']").click
end
click_button '.ei-icon-check'
end
end
但產量只是:
########
{}
[{"id":2,"number":"2","name":"project2","description":"Some notes","archived":false,"customer_id":2,"created_at":"2015-11-30T16:05:40.160+01:00","updated_at":"2015-11-30T16:05:40.160+01:00","rate_type":null,"hourly_rate":null,"service_rates":null,"budget_type":null,"budget_rate":null,"category":"A","deadline":null}]
[{"id":2,"name":"service2","description":"Some notes","archived":false,"created_at":"2015-11-30T16:05:40.173+01:00","updated_at":"2015-11-30T16:05:40.173+01:00","billable":null,"hourly_rate":null}]
########
這就是我的spec_helper.rb
:
require 'devise'
# Setup Capybara
require 'capybara/rspec'
require 'capybara/poltergeist'
Capybara.always_include_port = true
Capybara.javascript_driver = :poltergeist
# Use SimpleCov for code coverage
require 'simplecov'
require 'simplecov-shield'
SimpleCov.start 'rails'
SimpleCov.formatters = [
SimpleCov::Formatter::HTMLFormatter,
SimpleCov::Formatter::ShieldFormatter
]
# This file is copied to spec/ when you run 'rails generate rspec:install'
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
require 'rspec/rails'
require 'shoulda-matchers'
# Requires supporting ruby files with custom matchers and macros, etc, in
# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
# run as spec files by default. This means that files in spec/support that end
# in _spec.rb will both be required and run as specs, causing the specs to be
# run twice. It is recommended that you do not name files matching this glob to
# end with _spec.rb. You can configure this pattern with with the --pattern
# option on the command line or in ~/.rspec, .rspec or `.rspec-local`.
Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }
# Checks for pending migrations before tests are run.
# If you are not using ActiveRecord, you can remove this line.
ActiveRecord::Migration.check_pending! if defined?(ActiveRecord::Migration)
module ControllerMacros
def attributes_with_foreign_keys(*args)
FactoryGirl.build(*args).attributes.delete_if do |k, v|
['id', 'type', 'foreign_id', 'foreign_type', 'created_at', 'updated_at'].member?(k)
end
end
end
RSpec.configure do |config|
config.use_transactional_fixtures = false
config.use_instantiated_fixtures = false
config.mock_with :rspec
# Use FactoryGirl for fixtures
config.include FactoryGirl::Syntax::Methods
# Auto-detect spec types
config.infer_spec_type_from_file_location!
# Insert devise helpers in controller specs
config.include Devise::TestHelpers, type: :controller
config.include Warden::Test::Helpers
config.extend ControllerMacros, type: :controller
config.include ControllerMacros
# Run specs in random order to surface order dependencies. If you find an
# order dependency and want to debug it, you can fix the order by providing
# the seed, which is printed after each run.
# --seed 1234
config.order = 'random'
config.before(:suite) do
Warden.test_mode!
# Clean all tables to start
DatabaseCleaner.clean_with :truncation
# Use transactions for tests
DatabaseCleaner.strategy = :transaction
# Truncating doesn't drop schemas, ensure we're clean here, app *may not* exist
Apartment::Tenant.drop('test') rescue nil
# Create the default tenant for our tests
Account.create!(name: 'Test', domain: 'test', email: '[email protected]')
end
config.before(:each) do
# Start transaction for this test
DatabaseCleaner.start
# Switch into the default tenant
Apartment::Tenant.switch! 'test'
# Use Timecop to freeze times on time-critical tests
Timecop.return
end
config.after(:each) do
# Reset tentant back to `public`
Apartment::Tenant.reset
# Rollback transaction
DatabaseCleaner.clean
end
end
更新
OK,我覺得問題不在於此:
使用FactoryGirl創建模型(如FactoryGirl.create(:project)
)後,記錄在控制器中不可用。如果我喜歡寫東西
@foo = Project.all.to_json
在我的控制器,並要顯示在我看來這個數據,我只是得到[]
(主叫save_and_open_page
後)。
我雖然FactoryGirl.create
直接寫數據到數據庫?爲什麼我的控制器方法中沒有可用的數據?
更新2
添加
config.before(:each, :js => true) do
DatabaseCleaner.strategy = :truncation
end
解決了這個問題,但現在我得到:
Failure/Error: user = FactoryGirl.create(:user)
ActiveRecord::RecordNotUnique:
PG::UniqueViolation: ERROR: duplicate key value violates unique constraint "index_users_on_lastname"
DETAIL: Key (lastname)=(Kautzer) already exists.
: INSERT INTO "users" ("email", "initial", "firstname", "lastname", "encrypted_password", "archived", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING "id"
我以爲數據庫每次測試後得到清潔?
更新3
無視,最後一個問題是我的數據庫設置中的一個錯誤。
不是_exactly_我的問題和解決方案,但它導致了我的解決方案。故事的道德是:使用FactoryCube時使用'DatabaseCleaner',並正確設置它們。 +1謝謝 –