rails - FactoryGirl 保留的对象在 Controller 中不可用
rails - Objects persisted by FactoryGirl are not available in Controller
我正在为管理命名空间中的控制器编写测试。使用 RSpec (3.5.0)、FactoryGirl (4.8.0)、DatabaseCleaner (1.5.3) 和 Mongoid (6.0.3)。
问题是这些测试行为很奇怪。在测试 GET index
请求时,FactoryGirl 生成的对象已成功创建并持久化。但是,控制器似乎没有找到它们。
我有三个不同的控制器。三分之二的人有这个问题,第三个就像一个魅力。代码是相同的(除了命名)唯一的区别是工作控制器的资源是嵌套的。
配饰作品:
describe "GET #index", get: true do
let (:accessory) { FactoryGirl.create(:accessory) }
before do
get :index, params: { category_id: accessory.category_id.to_s }, session: valid_session, format: :json
end
it "responses with OK status" do
expect(response).to have_http_status(:success)
end
it "responses with a non-empty Array" do
expect(json_body).to be_kind_of(Array)
expect(json_body.length).to eq(1)
end
it "responses with JSON containing accessory" do
expect(response.body).to be_json
expect(json_body.first.with_indifferent_access).to match({
id: accessory.to_param,
name: 'Test accessory',
description: 'This is an accessory',
car_model: 'xv',
model_year: '2013',
images: be_kind_of(Array),
category_id: accessory.category.to_param,
dealer_id: accessory.dealer.to_param,
url: be_kind_of(String)
})
end
end
而类别的则没有:
describe "GET #index", get: true do
let (:category) { FactoryGirl.create(:category) }
before do
get :index, params: {}, session: valid_session, format: :json
end
it "responses with OK status" do
expect(response).to have_http_status(:success)
end
it "responses with a non-empty Array" do
expect(json_body).to be_kind_of(Array)
expect(json_body.length).to eq(1)
end
it "responses with JSON containing category" do
expect(response.body).to be_json
expect(json_body.first.with_indifferent_access).to match({
id: category.to_param,
name: 'Test category',
image: be_kind_of(String),
url: be_kind_of(String)
})
end
end
如您所见,逻辑是相同的:在 before
挂钩中发出请求并使用 let
设置对象。
另一个奇怪的事情是 GET show
测试具有相同逻辑的类别非常有效。
在这些问题 (1, ) 中,他们说这可能是由于 DatabaseCleaner 策略,应该使用 truncation
而不是 transaction
策略。我这样做是因为 Mongoid 只允许 truncation
。而且我也没有使用启用 JavaScript 的测试,并特别告诉 rspec 到 use_transactional_fixtures = false
RSpec FactoryGirl 和 DatabaseCleaner 的配置:
RSpec.configure do |config|
config.include FactoryGirl::Syntax::Methods
config.before(:suite) do
DatabaseCleaner.strategy = :truncation
DatabaseCleaner.clean_with(:truncation)
end
config.before(:each, :js => true) do
DatabaseCleaner.strategy = :truncation
end
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
end
我能够通过发出请求并在每个示例中创建一个对象来使这些测试通过,而不是使用 before
和 let
。但我认为它应该适用于他们。
控制器索引方法是默认的:
def index
@thing = Thing.all
end
你对这种奇怪的行为有什么想法吗?
请尝试 let!
而不是 let
。
请注意 let
是惰性求值的。类别数据在您调用 category.to_param
时生成。 before
块中不存在。
另见 https://relishapp.com/rspec/rspec-core/v/3-5/docs/helper-methods/let-and-let
我正在为管理命名空间中的控制器编写测试。使用 RSpec (3.5.0)、FactoryGirl (4.8.0)、DatabaseCleaner (1.5.3) 和 Mongoid (6.0.3)。
问题是这些测试行为很奇怪。在测试 GET index
请求时,FactoryGirl 生成的对象已成功创建并持久化。但是,控制器似乎没有找到它们。
我有三个不同的控制器。三分之二的人有这个问题,第三个就像一个魅力。代码是相同的(除了命名)唯一的区别是工作控制器的资源是嵌套的。
配饰作品:
describe "GET #index", get: true do
let (:accessory) { FactoryGirl.create(:accessory) }
before do
get :index, params: { category_id: accessory.category_id.to_s }, session: valid_session, format: :json
end
it "responses with OK status" do
expect(response).to have_http_status(:success)
end
it "responses with a non-empty Array" do
expect(json_body).to be_kind_of(Array)
expect(json_body.length).to eq(1)
end
it "responses with JSON containing accessory" do
expect(response.body).to be_json
expect(json_body.first.with_indifferent_access).to match({
id: accessory.to_param,
name: 'Test accessory',
description: 'This is an accessory',
car_model: 'xv',
model_year: '2013',
images: be_kind_of(Array),
category_id: accessory.category.to_param,
dealer_id: accessory.dealer.to_param,
url: be_kind_of(String)
})
end
end
而类别的则没有:
describe "GET #index", get: true do
let (:category) { FactoryGirl.create(:category) }
before do
get :index, params: {}, session: valid_session, format: :json
end
it "responses with OK status" do
expect(response).to have_http_status(:success)
end
it "responses with a non-empty Array" do
expect(json_body).to be_kind_of(Array)
expect(json_body.length).to eq(1)
end
it "responses with JSON containing category" do
expect(response.body).to be_json
expect(json_body.first.with_indifferent_access).to match({
id: category.to_param,
name: 'Test category',
image: be_kind_of(String),
url: be_kind_of(String)
})
end
end
如您所见,逻辑是相同的:在 before
挂钩中发出请求并使用 let
设置对象。
另一个奇怪的事情是 GET show
测试具有相同逻辑的类别非常有效。
在这些问题 (1, truncation
而不是 transaction
策略。我这样做是因为 Mongoid 只允许 truncation
。而且我也没有使用启用 JavaScript 的测试,并特别告诉 rspec 到 use_transactional_fixtures = false
RSpec FactoryGirl 和 DatabaseCleaner 的配置:
RSpec.configure do |config|
config.include FactoryGirl::Syntax::Methods
config.before(:suite) do
DatabaseCleaner.strategy = :truncation
DatabaseCleaner.clean_with(:truncation)
end
config.before(:each, :js => true) do
DatabaseCleaner.strategy = :truncation
end
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
end
我能够通过发出请求并在每个示例中创建一个对象来使这些测试通过,而不是使用 before
和 let
。但我认为它应该适用于他们。
控制器索引方法是默认的:
def index
@thing = Thing.all
end
你对这种奇怪的行为有什么想法吗?
请尝试 let!
而不是 let
。
请注意 let
是惰性求值的。类别数据在您调用 category.to_param
时生成。 before
块中不存在。
另见 https://relishapp.com/rspec/rspec-core/v/3-5/docs/helper-methods/let-and-let