1

I'm working on an application that reads JSON content from files and uses them to produce output. I'm testing with RSpec, and my specs are littered with JSON literal content all over the place. There's a ton of duplication, the files are big and hard to read, and it's getting to the point where it's so painful to add new cases, it's discouraging me from covering the corner cases.

Is there a good strategy for me to reuse large sections of JSON in my specs? I'd like to store the JSON somewhere that's not in the spec file, so I can focus on the test logic in the specs, and just understand which example JSON I'm using.

I understand that if the tests are hard to write, I may need to refactor the application, but until I can get the time to do that, I need to cover these test cases.

Below is one modified example from the application. I have to load many different JSON formatted strings like this, many are considerably larger and more complex:

RSpec.describe DataGenerator do      
  describe "#create_data" do     
    let(:input){
      '{ "schema": "TEST_SCHEMA",
         "tables": [
           { "name": "CASE_INFORMATION",
             "rows": 1,
             "columns": [
               { "name": "case_location_id", "type": "integer", "initial_value": "10000", "strategy": "next" },
               { "name": "id", "type": "integer", "delete_key": true, "initial_value": "10000", "strategy": "next" }
             ]
           }
         ]
       }'
    }
    it "generates the correct number of tables" do
      generator = DataGenerator.new(input)
      expect(generator.tables.size).to eq 1
    end
  end
end
2
  • 1
    Could you give an example of some of your test cases? What are you testing, and what literal JSON is being used in your RSpec tests? Commented Aug 8, 2014 at 13:37
  • @AlexP I added an example to give you a flavor of what I'm testing. This is a trivial case, but I think it lays out my approach and needs. Commented Aug 8, 2014 at 15:12

1 Answer 1

1

We had a very same problem. We solved it by creating following helpers:

module JsonHelper
  def get_json(name)
    File.read(Rails.root.join 'spec', 'fixtures', 'json', "#{name}.json")
  end
end

We moved all the json into files in spec/fixtures/json folder. Now you will eb able to use it as:

include JsonHelper

let(:input){ get_json :create_data_input }

Naturally you can tweak it as mach as you like/need. For example we were stubbing external services json responses, so we created get_service_response(service_name, request_name, response_type) helper. It is much more readable now when we use get_service_response('cdl', 'reg_lookup', 'invalid_reg')

assuming you put your json into 'create_data_input`

Sign up to request clarification or add additional context in comments.

2 Comments

That should work great for me to pull the JSON out of the specs and be able to reuse it easily, thank you.
Also, I'm not using Rails, so my method uses: File.read([Dir.getwd, 'spec', 'fixtures', 'json', "#{name}.json"].join('/'))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.