Rswag seems to be a cool tool to specify API in integration test. It is my first time to try, but stuck in FactoryBot creation. Here are what I did:
In rails_helper.rb, added the require and load support helper files:
require 'rspec/rails'
require 'factory_bot_rails'
Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }
In spec_helper.rb, added to include the support helpers:
RSpec.configure do |config|
config.color = true
config.order = :random
config.include RequestHelpers, type: :request
In spec/support folder, one file for FactoryBot, and one file for some helpers:
RSpec.configure do |config|
config.include FactoryBot::Syntax::Methods
end
module RequestHelpers
include Rack::Test::Methods
def json
JSON.parse(last_response.body)
end
def get_with_token(path, params={})
header "Authorization", "Bearer #{gen_jwt}"
get path, params
end
def gen_jwt
payload = {email: 'user@test.com'}
token = JWT.encode(payload, Rails.application.config.jwt_secret, 'HS256')
end
end
A factory file created as spec/factories/node.rb
FactoryBot.define do
factory :node, class: Node do
fqdn { "node_single.test.com" }
Platform { "ubuntu" }
IP { "192.168.99.1" }
isDeleted { false }
end
factory :node_list .... # create a list with sequence
Then, the following traditional rspec api test passed:
# spec/controllers/api/v1/nodes_controller_spec.rb
RSpec.describe 'nodes', type: :request do
describe 'index' do
context 'pagination' do
before(:each) do
create_list(:node_list, 32)
end
it 'get first page' do
ops = { pageSize: 10, pageNumber: 1 }
get_with_token "/api/v1/nodes", ops
expect(json["meta"]["total-record-number"]).to eq(32)
expect(json["data"].length).to eq(10)
end
end
end
But when tried to develop a rswag test file, it got failed...
require 'swagger_helper'
describe 'Nodes API', type: :request, swagger_doc: 'api/v1/swagger.json' do
TAGS_NODE = Node.freeze
path '/api/v1/nodes' do
get 'Get all servers' do
tags TAGS_NODE
produces 'application/json'
parameter name: :searchString, in: :query, type: :string
parameter name: :searchColumn, in: :query, type: :string
parameter name: :Authorization, in: :header, type: :string
let(:Authorization) { 'Bearer ' + gen_jwt }
let!(:nodes) { create_list(:node_list, 32) }
response '200', 'Servers found' do
let(:searchString) { '' }
let(:searchColumn) { '' }
run_test! do |repsonse|
data = JSON.parse(response.body)
puts data
end
end
end
end
end
It failed with following error:
rspec spec/integration/api/v1/nodes_spec.rb
Randomized with seed 18293
F
Failures:
1) Nodes API /api/v1/nodes get Servers found returns a 200 response
Failure/Error: let!(:nodes) { create_list(:node_list, 32) }
SystemStackError:
stack level too deep
# /usr/local/rvm/gems/ruby-2.4.5/gems/activesupport-5.2.3/lib/active_support/inflector/methods.rb:405:in `block in apply_inflections'
# /usr/local/rvm/gems/ruby-2.4.5/gems/activesupport-5.2.3/lib/active_support/inflector/methods.rb:405:in `apply_inflections'
# /usr/local/rvm/gems/ruby-2.4.5/gems/activerecord-5.2.3/lib/active_record/core.rb:242:in `inspect'
# /usr/local/rvm/gems/ruby-2.4.5/gems/activerecord-5.2.3/lib/active_record/core.rb:242:in `inspect'
......
# /usr/local/rvm/gems/ruby-2.4.5/gems/factory_bot-5.1.0/lib/factory_bot/decorator/new_constructor.rb:9:in `new'
# /usr/local/rvm/gems/ruby-2.4.5/gems/factory_bot-5.1.0/lib/factory_bot/decorator.rb:18:in `send'
# /usr/local/rvm/gems/ruby-2.4.5/gems/factory_bot-5.1.0/lib/factory_bot/decorator.rb:10:in `method_missing'
# /usr/local/rvm/gems/ruby-2.4.5/gems/factory_bot-5.1.0/lib/factory_bot/decorator/invocation_tracker.rb:11:in `method_missing'
# /usr/local/rvm/gems/ruby-2.4.5/gems/factory_bot-5.1.0/lib/factory_bot/decorator.rb:18:in `send'
# /usr/local/rvm/gems/ruby-2.4.5/gems/factory_bot-5.1.0/lib/factory_bot/decorator.rb:10:in `method_missing'
# /usr/local/rvm/gems/ruby-2.4.5/gems/factory_bot-5.1.0/lib/factory_bot/configuration.rb:23:in `block in initialize'
# /usr/local/rvm/gems/ruby-2.4.5/gems/factory_bot-5.1.0/lib/factory_bot/attribute_assigner.rb:51:in `instance_exec'
# /usr/local/rvm/gems/ruby-2.4.5/gems/factory_bot-5.1.0/lib/factory_bot/attribute_assigner.rb:51:in `build_class_instance'
# /usr/local/rvm/gems/ruby-2.4.5/gems/factory_bot-5.1.0/lib/factory_bot/attribute_assigner.rb:13:in `object'
# /usr/local/rvm/gems/ruby-2.4.5/gems/factory_bot-5.1.0/lib/factory_bot/evaluation.rb:13:in `object'
# /usr/local/rvm/gems/ruby-2.4.5/gems/factory_bot-5.1.0/lib/factory_bot/strategy/create.rb:9:in `result'
# /usr/local/rvm/gems/ruby-2.4.5/gems/factory_bot-5.1.0/lib/factory_bot/factory.rb:43:in `run'
# /usr/local/rvm/gems/ruby-2.4.5/gems/factory_bot-5.1.0/lib/factory_bot/factory_runner.rb:29:in `block in run'
# /usr/local/rvm/gems/ruby-2.4.5/gems/factory_bot-5.1.0/lib/factory_bot/factory_runner.rb:28:in `run'
# /usr/local/rvm/gems/ruby-2.4.5/gems/factory_bot-5.1.0/lib/factory_bot/strategy_syntax_method_registrar.rb:20:in `block in define_singular_strategy_method'
# /usr/local/rvm/gems/ruby-2.4.5/gems/factory_bot-5.1.0/lib/factory_bot/strategy_syntax_method_registrar.rb:32:in `block (2 levels) in define_list_strategy_method'
# /usr/local/rvm/gems/ruby-2.4.5/gems/factory_bot-5.1.0/lib/factory_bot/strategy_syntax_method_registrar.rb:32:in `initialize'
# /usr/local/rvm/gems/ruby-2.4.5/gems/factory_bot-5.1.0/lib/factory_bot/strategy_syntax_method_registrar.rb:32:in `new'
# /usr/local/rvm/gems/ruby-2.4.5/gems/factory_bot-5.1.0/lib/factory_bot/strategy_syntax_method_registrar.rb:32:in `block in define_list_strategy_method'
# ./spec/integration/api/v1/nodes_spec.rb:14:in `block (4 levels) in <top (required)>'
The trace is very long, I tried to put sth useful I guess
Did some google search also in stackoverflow, but can not find any clue. Thanks a lot for your help!
Update
Same error when change to use 'before' instead of let, can not create records in database in rswag integration case, but it does work in model spec and controller spec...
After another day day, happened to find that it is because of the following code:
TAGS_NODE = Node.freeze
...
tags TAGS_NODE
After removed the TAGS_NODE and changed to tags 'Nodes'
, then everything went well.
But still dont understand the underlying reasons...