On Wednesday, 27 February 2019 16:19:16 UTC+1, belgoros wrote:
>
>
>
> On Wednesday, 27 February 2019 16:05:18 UTC+1, belgoros wrote:
>>
>>
>>
>> On Wednesday, 27 February 2019 16:02:23 UTC+1, Jon Rowe wrote:
>>>
>>> You need to include your concern in your fake controller.
>>>
>>> We do have the anonymous controller helpers for this purpose. See: 
>>> https://relishapp.com/rspec/rspec-rails/docs/controller-specs/anonymous-controller
>>>
>>> Although you’ll still need to include the concern.
>>>
>>
>> Weird, I have it defined as follows without including the module Response 
>> as it was included in ApplicationController:
>>
>> require 'rails_helper'
>>
>>
>> class FakeController < ApplicationController
>> end
>>
>>
>> RSpec.describe FakeController, type: :controller do  
>>   it_should_behave_like "JSON Responsive controller" do 
>>     let(:instance) { FakeController.new }
>>   end
>>
>> end 
>>
>>>
>>> Cheers
>>> Jon Rowe
>>> ---------------------------
>>> [email protected]
>>> jonrowe.co.uk
>>>
>>> On 27 February 2019 at 13:25, belgoros wrote:
>>>
>>> On Wednesday, 27 February 2019 14:08:53 UTC+1, belgoros wrote:
>>>
>>>
>>>
>>> On Wednesday, 27 February 2019 12:02:12 UTC+1, Jon Rowe wrote:
>>>
>>> If you need a controller you need a controller spec, its not practical 
>>> to instantiate a controller on your own, one of the many reasons why they 
>>> are recommended against by the Rails team now.
>>>
>>> Otherwise you need to test the behaviour of the end result, e.g. create 
>>> a set of shared examples for your concern and use them in every 
>>> request/system/integration test for the routes concerned.
>>>
>>>
>>> I tried it as follows:
>>>
>>> #spec/controllers/concerns/response_spec.rb
>>> require 'rails_helper'
>>> class FakeController < ApplicationController
>>> end
>>> RSpec.describe FakeController, type: :controller do
>>>
>>>   let
>>> (:controller) { FakeController.new}
>>>
>>>   
>>>   
>>> FakeModel = Struct.new(:name)
>>>
>>>   describe 
>>> 'Response concern' do
>>>
>>>     context 
>>> '#json_response' do
>>>
>>>       it 
>>> 'renders JSON response' do
>>>
>>>         fake_model 
>>> = FakeModel.new('example')
>>>
>>>         result 
>>> = controller.json_response(fake_model)
>>>
>>>         puts 
>>> "result: #{result.inspect}"
>>>        
>>>       
>>> end
>>>
>>>     
>>> end
>>>
>>>     
>>>   
>>> end
>>> end
>>>
>>> but it fails with:
>>>
>>> rspec spec/controllers/concerns/response_spec.rb 
>>>
>>> F
>>>
>>> Failures:
>>>
>>>   1) FakeController Response concern #json_response renders JSON 
>>> response
>>>
>>>      Failure/Error: render response
>>>
>>>      
>>>
>>>      Module::DelegationError:
>>>
>>>        ActionController::Metal#status= delegated to @_response.status=, 
>>> but @_response is nil: #<FakeController:0x00007fd004810700 @_routes=nil, 
>>> @_request=nil, @_response=nil, @_config={}, @_db_runtime=109.12200000000001>
>>>
>>>      # ./app/controllers/concerns/response.rb:6:in `json_response'
>>>
>>>      # ./spec/controllers/concerns/response_spec.rb:14:in `block (4 
>>> levels) in <top (required)>'
>>>
>>>      # ------------------
>>>
>>>      # --- Caused by: ---
>>>
>>>      # NoMethodError:
>>>
>>>      #   undefined method `status=' for nil:NilClass
>>>
>>>      #   ./app/controllers/concerns/response.rb:6:in `json_response'
>>>
>>> Finished in 0.17825 seconds (files took 1.12 seconds to load)
>>>
>>> 1 example, 1 failure
>>>
>>>
>>> What am I missing here ?
>>>
>>>
>>> I modified by creating a shared example as follows:
>>>
>>> #spec/shared/json_response.rb
>>> require 'rails_helper'
>>> RSpec.shared_examples 'JSON Responsive controller' do |controller_class|
>>>
>>>   let
>>> (:controller_class) { including_class.new }
>>>
>>>
>>>
>>>   it 
>>> 'render JSON response' do
>>>
>>>     expect
>>> (controller_class).to respond_to(:json_response)
>>>
>>>   
>>> end
>>> end
>>>
>>>
>>> Then by using it in a controller spec:
>>> #spec/controllers/concerns/fake_controller_spec.rb
>>> require 'rails_helper'
>>> class FakeController < ApplicationController
>>> end
>>> RSpec.describe FakeController, type: :controller do
>>>
>>>   it_behaves_like 
>>> 'JSON Responsive controller', FakeController
>>> end
>>>
>>>
>>> But it fails as follows:
>>>
>>> Failures:
>>>
>>>   1) FakeController behaves like JSON Responsive class render JSON 
>>> response
>>>
>>>      Failure/Error: expect(controller_class).to respond_to(
>>> :json_response)
>>>
>>>        expected FakeController to respond to :json_response
>>>
>>>      Shared Example Group: "JSON Responsive class" called from 
>>> ./spec/controllers/concerns/fake_controller_spec.rb:7
>>>
>>>      # ./spec/shared/json_response.rb:7:in `block (2 levels) in <main>'
>>>
>>>
> The error is due the call render response in Response module:
> def json_response(object, status = :ok, opts = {})
>     response = {json: object, status: status}.merge(opts)
>     puts "++++++++ response: #{response.inspect}"
>     render response
>   end
>
> The 'puts' displays:
>
> ++++++++ response: {:json=>#<Double :model>, :status=>:ok}
>
>  
> But the error says is related to Module::DelegationError:
>
> Module::DelegationError: 
>
> ActionController::Metal#status= delegated to @_response.status=, but 
> @_response is nil: #<FakeController:0x00007faf08fe0920 @_routes=nil, 
> @_request=nil, @_response=nil, @_config={}, @_db_runtime=181.55> 
>
> Shared Example Group: "JSON Responsive controller" called from ./spec/
> controllers/concerns/fake_controller_spec.rb:7 
>
> # ./app/controllers/concerns/response.rb:7:in `json_response' 
>
> # ./spec/shared/json_response.rb:13:in `block (3 levels) in <main>' 
>
> # ------------------ 
>
> # --- Caused by: --- 
>
> # NoMethodError: 
>
> # undefined method `status=' for nil:NilClass 
>
> # ./app/controllers/concerns/response.rb:7:in `json_response'
>

Finally, the version that works:

#spec/shared/json_response.rb


require 'rails_helper'


RSpec.shared_examples 'JSON Responsive controller' do |including_controller|
  let(:instance) { including_controller.new }


  it 'should respond to #json_response' do
    expect(instance).to respond_to(:json_response)
  end


  it 'should respond #respond_with_errors' do
    expect(instance).to respond_to(:respond_with_errors)
  end
  
  it 'should respond to #paginated_response_status' do
    expect(instance).to respond_to(:paginated_response_status)
  end


  context '#paginated_response_status' do   
    it 'return 200 if collection is not paginated' do
      expect(instance.paginated_response_status([1])).to eq :ok
    end


    it 'return 206 if collection is paginated' do
      collection = (1..35).to_a
      expect(instance.paginated_response_status(collection)).to eq :
partial_content
    end
  end
end



It will fail if I try to call *Response* module methods that call *render* 
inside. Can't figure out how to get around if it.

>
>  
>>>
>>>

-- 
You received this message because you are subscribed to the Google Groups 
"rspec" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/rspec/4bd5b24c-3550-4f0a-98db-921a086570b1%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to