Writing test for controller method
-
21-12-2019 - |
سؤال
I have a protected method in controller and need to write the test case for it. The method is
def source
@source.present? ? @source.class : Association.reflect_on_association(source.to_sym).klass
end
where @source will be an object and source will be a string.
I have no idea how to write the test case for this method.
edit
Here is what I am trying
subject { @controller }
describe '#source' do
let(:source_object) { create :program_type}
describe "Object is not present" do
it 'should reflect on association and return the reflection class' do
subject.stubs(:source_identifier).returns("program_type")
subject.send(:source).must_equal ProgramType
end
end
describe "Object is present" do
it 'should return the class of the object' do
subject.send(:source).must_equal source_object.class
end
end
end
Thanks in advance.
المحلول 3
I fixed it. The problem was return string in the first test and object in the second. Here is what i did to fix.
describe '#source' do
describe "Object is not present" do
it 'should reflect on association and return the reflection class' do
subject.stubs(:source_identifier).returns("program_types")
subject.send(:source).must_equal ProgramType
end
end
describe "Object is present" do
it 'should return the class of the object' do
subject.instance_variable_set(:@source, create(:program_type))
subject.send(:source).must_equal ProgramType
end
end
end
نصائح أخرى
For testing controllers I have following tutorials as references
1 - http://everydayrails.com/2012/04/07/testing-series-rspec-controllers.html
2 - https://gist.github.com/delphaber/d898152eee04cea4964f (more of a cheet sheet)
However it seems to me your method should move to a model or lib. (I'm just guessing by looking at your code) and another thing is if you cannot isolate a method for testing, probably you might have to re-think about the design :)
In general I would suggest not writing tests for protected controller methods, they should be exercised by whichever publicly facing method calls them.
In your case so long as you test whatever calls source, you will be testing source.
If you really need to though you can do;
@controller = MyController.new
@controller.send(:source) #this will call source