【发布时间】:2017-05-11 14:52:31
【问题描述】:
我正在 admin 命名空间中为我的控制器编写测试。使用 RSpec (3.5.0)、FactoryGirl (4.8.0)、DatabaseCleaner (1.5.3) 和 Mongoid (6.0.3)。
问题是这些测试表现得很奇怪。在测试GET index 请求时,FactoryGirl 生成的对象被成功创建并持久化。但是,控制器似乎没有找到它们。
我有三个不同的控制器。 3 人中有 2 人有此问题,而第 3 人则很有魅力。代码是一样的(除了命名),唯一的区别是工作控制器的资源是嵌套的。
配饰作品:
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、2)中,他们说这可能是由于 DatabaseCleaner 策略,应该使用 truncation 而不是 transaction 策略。我这样做是因为 Mongoid 只允许 truncation。而且我也没有使用支持 JavaScript 的测试,并专门告诉 rspec 给use_transactional_fixtures = false
FactoryGirl 和 DatabaseCleaner 的 RSpec 配置:
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
你对这种奇怪的行为有什么想法吗?
【问题讨论】:
标签: ruby-on-rails rspec mongoid factory-bot database-cleaner