RSpec controller spec: How to test rendered JSON?












1














I'm trying to test a simple controller's action of a Rails API



Here's the controller in question:



class Api::TransactionsController < ApplicationController
def index
transactions = Transaction.all
json = TransactionSerializer.render(transactions)
render json: json
end
end


Here are my specs so far



require 'rails_helper'

RSpec.describe Api::TransactionsController do
describe '.index' do
context "when there's no transactions in the database" do
let(:serialized_data) { .to_json }

before { allow(TransactionSerializer).to receive(:render).with().and_return(serialized_data) }
after { get :index }

specify { expect(TransactionSerializer).to receive(:render).with() }
specify { expect(response).to have_http_status(200) }
end
end
end


I want to test the response. Something like in this Stack Overflow question How to check for a JSON response using RSpec?:



specify { expect(response.body).to eq(.to_json) }



My problem is that response.body is an empty string. Why is that ?










share|improve this question
























  • What is it that you are expecting in response.body? Also, better practice to have expect(response).to have_http_status(:success).
    – Aaditya Maheshwari
    Dec 27 '18 at 18:29








  • 1




    Because your database in test environment is empty.
    – Aleksei Matiushkin
    Dec 27 '18 at 18:49










  • Yes the database is empty, so the response should be an empty array. Besides as you can see in the specs, I stubbed the serializer to return an empty array.
    – David B.
    Dec 27 '18 at 19:50






  • 2




    I think that you need to call get :index in a before block, otherwise there is not response body.
    – eikes
    Dec 27 '18 at 20:54










  • Yes it works and it makes sense. thanks
    – David B.
    Dec 27 '18 at 21:28
















1














I'm trying to test a simple controller's action of a Rails API



Here's the controller in question:



class Api::TransactionsController < ApplicationController
def index
transactions = Transaction.all
json = TransactionSerializer.render(transactions)
render json: json
end
end


Here are my specs so far



require 'rails_helper'

RSpec.describe Api::TransactionsController do
describe '.index' do
context "when there's no transactions in the database" do
let(:serialized_data) { .to_json }

before { allow(TransactionSerializer).to receive(:render).with().and_return(serialized_data) }
after { get :index }

specify { expect(TransactionSerializer).to receive(:render).with() }
specify { expect(response).to have_http_status(200) }
end
end
end


I want to test the response. Something like in this Stack Overflow question How to check for a JSON response using RSpec?:



specify { expect(response.body).to eq(.to_json) }



My problem is that response.body is an empty string. Why is that ?










share|improve this question
























  • What is it that you are expecting in response.body? Also, better practice to have expect(response).to have_http_status(:success).
    – Aaditya Maheshwari
    Dec 27 '18 at 18:29








  • 1




    Because your database in test environment is empty.
    – Aleksei Matiushkin
    Dec 27 '18 at 18:49










  • Yes the database is empty, so the response should be an empty array. Besides as you can see in the specs, I stubbed the serializer to return an empty array.
    – David B.
    Dec 27 '18 at 19:50






  • 2




    I think that you need to call get :index in a before block, otherwise there is not response body.
    – eikes
    Dec 27 '18 at 20:54










  • Yes it works and it makes sense. thanks
    – David B.
    Dec 27 '18 at 21:28














1












1








1







I'm trying to test a simple controller's action of a Rails API



Here's the controller in question:



class Api::TransactionsController < ApplicationController
def index
transactions = Transaction.all
json = TransactionSerializer.render(transactions)
render json: json
end
end


Here are my specs so far



require 'rails_helper'

RSpec.describe Api::TransactionsController do
describe '.index' do
context "when there's no transactions in the database" do
let(:serialized_data) { .to_json }

before { allow(TransactionSerializer).to receive(:render).with().and_return(serialized_data) }
after { get :index }

specify { expect(TransactionSerializer).to receive(:render).with() }
specify { expect(response).to have_http_status(200) }
end
end
end


I want to test the response. Something like in this Stack Overflow question How to check for a JSON response using RSpec?:



specify { expect(response.body).to eq(.to_json) }



My problem is that response.body is an empty string. Why is that ?










share|improve this question















I'm trying to test a simple controller's action of a Rails API



Here's the controller in question:



class Api::TransactionsController < ApplicationController
def index
transactions = Transaction.all
json = TransactionSerializer.render(transactions)
render json: json
end
end


Here are my specs so far



require 'rails_helper'

RSpec.describe Api::TransactionsController do
describe '.index' do
context "when there's no transactions in the database" do
let(:serialized_data) { .to_json }

before { allow(TransactionSerializer).to receive(:render).with().and_return(serialized_data) }
after { get :index }

specify { expect(TransactionSerializer).to receive(:render).with() }
specify { expect(response).to have_http_status(200) }
end
end
end


I want to test the response. Something like in this Stack Overflow question How to check for a JSON response using RSpec?:



specify { expect(response.body).to eq(.to_json) }



My problem is that response.body is an empty string. Why is that ?







ruby-on-rails ruby rspec rspec-rails






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Dec 27 '18 at 19:50









Aaditya Maheshwari

383211




383211










asked Dec 27 '18 at 18:10









David B.

182211




182211












  • What is it that you are expecting in response.body? Also, better practice to have expect(response).to have_http_status(:success).
    – Aaditya Maheshwari
    Dec 27 '18 at 18:29








  • 1




    Because your database in test environment is empty.
    – Aleksei Matiushkin
    Dec 27 '18 at 18:49










  • Yes the database is empty, so the response should be an empty array. Besides as you can see in the specs, I stubbed the serializer to return an empty array.
    – David B.
    Dec 27 '18 at 19:50






  • 2




    I think that you need to call get :index in a before block, otherwise there is not response body.
    – eikes
    Dec 27 '18 at 20:54










  • Yes it works and it makes sense. thanks
    – David B.
    Dec 27 '18 at 21:28


















  • What is it that you are expecting in response.body? Also, better practice to have expect(response).to have_http_status(:success).
    – Aaditya Maheshwari
    Dec 27 '18 at 18:29








  • 1




    Because your database in test environment is empty.
    – Aleksei Matiushkin
    Dec 27 '18 at 18:49










  • Yes the database is empty, so the response should be an empty array. Besides as you can see in the specs, I stubbed the serializer to return an empty array.
    – David B.
    Dec 27 '18 at 19:50






  • 2




    I think that you need to call get :index in a before block, otherwise there is not response body.
    – eikes
    Dec 27 '18 at 20:54










  • Yes it works and it makes sense. thanks
    – David B.
    Dec 27 '18 at 21:28
















What is it that you are expecting in response.body? Also, better practice to have expect(response).to have_http_status(:success).
– Aaditya Maheshwari
Dec 27 '18 at 18:29






What is it that you are expecting in response.body? Also, better practice to have expect(response).to have_http_status(:success).
– Aaditya Maheshwari
Dec 27 '18 at 18:29






1




1




Because your database in test environment is empty.
– Aleksei Matiushkin
Dec 27 '18 at 18:49




Because your database in test environment is empty.
– Aleksei Matiushkin
Dec 27 '18 at 18:49












Yes the database is empty, so the response should be an empty array. Besides as you can see in the specs, I stubbed the serializer to return an empty array.
– David B.
Dec 27 '18 at 19:50




Yes the database is empty, so the response should be an empty array. Besides as you can see in the specs, I stubbed the serializer to return an empty array.
– David B.
Dec 27 '18 at 19:50




2




2




I think that you need to call get :index in a before block, otherwise there is not response body.
– eikes
Dec 27 '18 at 20:54




I think that you need to call get :index in a before block, otherwise there is not response body.
– eikes
Dec 27 '18 at 20:54












Yes it works and it makes sense. thanks
– David B.
Dec 27 '18 at 21:28




Yes it works and it makes sense. thanks
– David B.
Dec 27 '18 at 21:28












1 Answer
1






active

oldest

votes


















1














Not sure what kind of serializer you're using. But, render is not a method on an ActiveModel::Serializer. Try this instead:



module Api
class TransactionsController < ApplicationController
def index
transactions = Transaction.all
render json: transactions
end
end
end


If your TransactionSerializer is an ActiveModel::Serializer, Rails will, by convention, just use it to serialize each Transaction record in the ActiveRecord::Relation.



And, test it like this:



require 'rails_helper'

describe Api::TransactionsController do
describe '#index' do
context "when there's no transactions in the database" do
let(:transactions) { Transaction.none }

before do
allow(Transaction).to receive(:all).and_return(transactions)

get :index
end

specify { expect(response).to have_http_status(200) }
specify { expect(JSON.parse(response.body)).to eq() }
end
end
end


Part of the problem here might have been that you weren't actually calling get :index until after the tests ran. You need to call it before the tests run.






share|improve this answer





















    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53949148%2frspec-controller-spec-how-to-test-rendered-json%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    1














    Not sure what kind of serializer you're using. But, render is not a method on an ActiveModel::Serializer. Try this instead:



    module Api
    class TransactionsController < ApplicationController
    def index
    transactions = Transaction.all
    render json: transactions
    end
    end
    end


    If your TransactionSerializer is an ActiveModel::Serializer, Rails will, by convention, just use it to serialize each Transaction record in the ActiveRecord::Relation.



    And, test it like this:



    require 'rails_helper'

    describe Api::TransactionsController do
    describe '#index' do
    context "when there's no transactions in the database" do
    let(:transactions) { Transaction.none }

    before do
    allow(Transaction).to receive(:all).and_return(transactions)

    get :index
    end

    specify { expect(response).to have_http_status(200) }
    specify { expect(JSON.parse(response.body)).to eq() }
    end
    end
    end


    Part of the problem here might have been that you weren't actually calling get :index until after the tests ran. You need to call it before the tests run.






    share|improve this answer


























      1














      Not sure what kind of serializer you're using. But, render is not a method on an ActiveModel::Serializer. Try this instead:



      module Api
      class TransactionsController < ApplicationController
      def index
      transactions = Transaction.all
      render json: transactions
      end
      end
      end


      If your TransactionSerializer is an ActiveModel::Serializer, Rails will, by convention, just use it to serialize each Transaction record in the ActiveRecord::Relation.



      And, test it like this:



      require 'rails_helper'

      describe Api::TransactionsController do
      describe '#index' do
      context "when there's no transactions in the database" do
      let(:transactions) { Transaction.none }

      before do
      allow(Transaction).to receive(:all).and_return(transactions)

      get :index
      end

      specify { expect(response).to have_http_status(200) }
      specify { expect(JSON.parse(response.body)).to eq() }
      end
      end
      end


      Part of the problem here might have been that you weren't actually calling get :index until after the tests ran. You need to call it before the tests run.






      share|improve this answer
























        1












        1








        1






        Not sure what kind of serializer you're using. But, render is not a method on an ActiveModel::Serializer. Try this instead:



        module Api
        class TransactionsController < ApplicationController
        def index
        transactions = Transaction.all
        render json: transactions
        end
        end
        end


        If your TransactionSerializer is an ActiveModel::Serializer, Rails will, by convention, just use it to serialize each Transaction record in the ActiveRecord::Relation.



        And, test it like this:



        require 'rails_helper'

        describe Api::TransactionsController do
        describe '#index' do
        context "when there's no transactions in the database" do
        let(:transactions) { Transaction.none }

        before do
        allow(Transaction).to receive(:all).and_return(transactions)

        get :index
        end

        specify { expect(response).to have_http_status(200) }
        specify { expect(JSON.parse(response.body)).to eq() }
        end
        end
        end


        Part of the problem here might have been that you weren't actually calling get :index until after the tests ran. You need to call it before the tests run.






        share|improve this answer












        Not sure what kind of serializer you're using. But, render is not a method on an ActiveModel::Serializer. Try this instead:



        module Api
        class TransactionsController < ApplicationController
        def index
        transactions = Transaction.all
        render json: transactions
        end
        end
        end


        If your TransactionSerializer is an ActiveModel::Serializer, Rails will, by convention, just use it to serialize each Transaction record in the ActiveRecord::Relation.



        And, test it like this:



        require 'rails_helper'

        describe Api::TransactionsController do
        describe '#index' do
        context "when there's no transactions in the database" do
        let(:transactions) { Transaction.none }

        before do
        allow(Transaction).to receive(:all).and_return(transactions)

        get :index
        end

        specify { expect(response).to have_http_status(200) }
        specify { expect(JSON.parse(response.body)).to eq() }
        end
        end
        end


        Part of the problem here might have been that you weren't actually calling get :index until after the tests ran. You need to call it before the tests run.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Dec 28 '18 at 6:14









        aridlehoover

        1,367912




        1,367912






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53949148%2frspec-controller-spec-how-to-test-rendered-json%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Angular Downloading a file using contenturl with Basic Authentication

            Olmecas

            Can't read property showImagePicker of undefined in react native iOS