Search code examples
factory-botrswag

FactoryBot failure in Rswag


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: '[email protected]'}
        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...


Solution

  • 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...